commit 46532baf4ab6d3ad2e92a0c95671a5515f76c023 Author: ClovertaTheTrilobita Date: Thu Feb 20 17:33:58 2025 +0800 rebase master diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..476e7f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +node_modules +*.env.prod +.venv +.xml +.idea +chat_bot.db +chat_bot.db-wal +chat_bot.db-shm +cloud_music_cookies.cookie +chat_history.json +/src/clover_music/qrcode.png +/chat.db +/chat_bot.db-wal +/chat_bot.db-shm +error.log +bili.cookie +*.log +*.mp4 +/bili.cookie +/src/configs/api_config.py +/src/resources/temp +/update_remote_code.py +/src/resources/image/report/* +/src/resources/image/lightnovel/* +/wenku8.cookie +/src/resources/image/yuc_wiki/* +src/clover_lightnovel/wenku8.cookie +src/clover_lightnovel/output1.html +*.pyc \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e5f7ea --- /dev/null +++ b/README.md @@ -0,0 +1,577 @@ +# SanYeCao-Nonebot + +## 📚介绍 + +

🌟三叶草bot 2.0🌟
+🚀使用Nonebot2+官方API搭建的QQ群聊机器人🚀

+Static Badge +Static Badge +last-commit +Static Badge

+

+ + +## 🔖亮点 + +- 基于[Nonebot2](https://nonebot.dev/),使用[QQ官方API](https://bot.q.qq.com/wiki/),更稳定、高效✨ +- 多种个性化用法,如天气、每日运势(~~机器人时尚单品~~)、点歌、编辑个人待办等,后续功能开发中🔧 +- 使用轻量化数据库sqlite管理数据,实现为每位用户单独存取数据🔍 +- 接入第三方大语言模型,实现AI交互💡 + +
+ +###### 我是菜比🏳️🏳️,纯新手写的python 问题肯定多 ,若有兴趣可以帮忙一起完善功能
+###### QQ交流群:[710101225](https://qm.qq.com/q/AQyepzKUJq) + +
+ +- ↑sly是代码领域大神, 👈 ClovertaTheTrilobita 写的 + +## 🌈目前功能: + +- [x] 待办 +- [x] 天气 +- [x] 今日运势 +- [x] 今日塔罗 +- [x] 点歌(网易云 需扫码登录 在 src\music 目录下)*目前cookie过期检测有bug,出现播放不了需要吧cookie文件删掉* +- [x] 图(返回图库中的图片) +- [x] 摸摸头 +- [x] 接入语言模型 +- [x] 搜索B站视频 +- [ ] 今日老婆 +- [x] 群老婆 +- [x] 鲁迅说 +- [x] 喜报、悲报 +- [x] 查询cf比赛 +- [x] 日报 +- [x] 查询热门轻小说 +- [x] 获取新番信息 + +#### 待办 +- **功能描述**: 用户可以添加、查询和删除个人待办事项。 +- **指令**: `/待办`, `/待办查询`, `/新建待办`, `/删除待办` + +#### 天气 +- **功能描述**: 提供当前天气信息。 +- **指令**: `/天气` + +#### 今日运势 +- **功能描述**: 提供用户的今日运势。 +- **指令**: `/今日运势` + +#### 今日塔罗 +- **功能描述**: 提供一张随机的塔罗牌及其解读。 +- **指令**: `/今日塔罗` + +#### 点歌 +- **功能描述**: 通过网易云音乐API点歌,并将音乐文件以QQ语音的形式发送至群聊。 快点一首你喜欢的歌给群友听吧! +- **指令**: `/点歌` +- **注意事项**: + - 使用网易云点歌需要另外安装依赖: npm install crypto-js + - 初次使用需要扫码登录网易云音乐。 + - 若cookie过期,需要删除 `cloud_music_cookies.cookie` 文件并重新扫码登录。 + +#### 图 +- **功能描述**: 返回图库中的图片。 +- **指令**: `/图` + +#### 摸摸头 +- **功能描述**: 与机器人进行互动,发送“摸摸头”的回复。 +- **指令**: `/摸摸头` + +#### 接入语言模型 +- **功能描述**: 使用第三方大语言模型进行交互。 +- **指令**: `/开启ai`, `/关闭ai` `/角色列表`,`/添加人设`, `/更新人设`, `/删除人设`, `/切换人设`, `/管理员注册` +- **注意事项**: + - 需要管理员身份认证。 + - AI功能为每个群单独启动,默认关闭。 + +#### 搜索B站视频 +- **功能描述**: 通过BV号搜索B站视频,并将视频文件发送至群聊。 +- **指令**: `/BV搜索 ` +- **注意事项**: + - 🚨注意: 由于QQ的限制,官方bot无法发送文件大于10M。 + - 需要安装 Chrome Driver。您需要首先确保自己的电脑安装了[Chrome Driver](https://developer.chrome.google.cn/docs/chromedriver?hl=zh-cn)。 + - 若没安装过,请参考教程:[chromedriver下载与安装方法,亲测可用-CSDN博客](https://blog.csdn.net/zhoukeguai/article/details/113247342) + - 程序第一次启动时,会获取B站的cookie保存至本地,使用selenium库完成,下载可能较慢,需要稍等一会儿。 + +#### 今日老婆 +- **功能描述**: 提供今日老婆的信息。 +- **指令**: `/今日老婆` +- **状态**: 待开发 + +#### 群老婆 +- **功能描述**: 提供群内成员的老婆信息。 +- **指令**: `/群老婆` + +#### 鲁迅说 +- **功能描述**: 提供鲁迅的经典语录。 +- **指令**: `/鲁迅说`,`/luxun` + +#### 喜报、悲报 +- **功能描述**: 提供喜报和悲报的信息。 +- **指令**: `/喜报`, `/悲报` + +#### 查询cf比赛 +- **功能描述**: 通过CodeForces官方API查询近期比赛。 +- **指令**: `/cf` + +#### 日报 +- **功能描述**: 提供每日的新闻或信息。 +- **指令**: `/日报` + +#### 查询热门轻小说 +- **功能描述**: 查询当前热门的轻小说。 +- **指令**: `/轻小说` + +#### 获取新番信息 +- **功能描述**: 获取当季动漫的新番信息和预期新番上线信息。 +- **指令**: `/本季新番`, `/新番观察` + +## 🛠️使用 + +- 关于Nonebot完整部署使用方法,请查看[官方文档](https://nonebot.dev/) + +
+ + +### ⚙️一、环境配置 + +**我们强烈建议您使用虚拟环境**,若您使用Anaconda发行版,请在终端输入 + +```powershell +conda create --name chatbot python=3.11 +``` + +创建conda环境。 + +或者将上述 *chatbot* 更换为你喜欢的名字。 + +🚫注意:机器人支持Static Badge的发行版,推荐使用Static Badge + +
+ +此机器人运行所需依赖已全部打包至***requirements.txt***,您只需回到项目根目录 + +在终端输入: + +```powershell +pip install -r requirements.txt +``` + +安装所需依赖。 + +
+ +**使用网易云点歌需要另外安装:** + +```powershell +npm install crypto-js +``` + +
+ +**使用BV搜索B站视频需要另外安装:**[Chrome Driver](https://googlechromelabs.github.io/chrome-for-testing/) + +安装教程:[chromedriver下载与安装方法,亲测可用-CSDN博客](https://blog.csdn.net/zhoukeguai/article/details/113247342) + +
+ +### ✒️二、配置所需文件 + +在一切开始前,你需要将项目根目录下的[example.env.prod](example.env.prod)文件更名为.env.prod,这是机器人的账号配置文件。 + +``` +DRIVER=~fastapi+~httpx+~websockets + +QQ_IS_SANDBOX=false + +QQ_BOTS=" +[ + { + "id": "xxx", + "token": "xxx", + "secret": "xxx", + "intent": { + "c2c_group_at_messages": true + }, + "use_websocket": true + } +] +" +``` +分别在id、token、secret处填写你的机器人ID,机器人Token和Apple Secret,需从[QQ开放平台](https://q.qq.com/)获取。 + +
+ +### 📍二、启动机器人 + +在项目根目录中,找到 *bot.py* ,在终端输入 + +```powershell +python bot.py +``` + +或者选择编译器启动,便可以启动机器人。 + +
+ +当然可以!以下是根据您提供的文件内容整理后的项目结构: + +### 🗒️ 三、项目结构 + +``` +SanYeCao-Nonebot:. +│ .gitignore +│ bot.py +│ chat_bot.db +│ example.env.prod +│ package-lock.json +│ package.json +│ pyproject.toml +│ README.md +│ requirements.txt +│ +├─node_modules +│ └─crypto-js +│ +└─src + ├─clover_image + │ └─get_image.py + │ + ├─clover_music + │ ├─cloud_music + │ │ ├─cloud_music_cookies.cookie + │ │ └─qrcode.png + │ └─netease_music + │ + ├─clover_openai + │ ├─api_config_example.py + │ └─api_config.py + │ + ├─clover_sqlite + │ ├─data_init + │ │ ├─init_tables.py + │ │ └─... + │ └─models + │ ├─models.py + │ └─... + │ + ├─clover_videos + │ └─billibili + │ ├─bilibili_search.py + │ └─... + │ + ├─configs + │ ├─path_config.py + │ ├─api_config_example.py + │ └─utils + │ ├─utils.py + │ └─... + │ + ├─plugins + │ ├─check.py + │ ├─todo.py + │ ├─weather.py + │ ├─fortune.py + │ ├─tarot.py + │ ├─music.py + │ ├─image.py + │ ├─petpet.py + │ ├─openai.py + │ ├─bilibili.py + │ ├─news.py + │ ├─light_novel.py + │ ├─anime.py + │ └─... + │ + └─resources + ├─font + │ ├─font.ttf + │ └─... + ├─image + │ ├─codeforces + │ │ ├─image1.png + │ │ └─... + │ ├─github_repo + │ │ ├─image2.png + │ │ └─... + │ ├─good_bad_news + │ │ ├─image3.png + │ │ └─... + │ ├─MaoYuNa + │ │ ├─image4.png + │ │ └─... + │ ├─rua + │ │ ├─image5.png + │ │ └─... + │ ├─tarot + │ │ ├─sideTarotImages + │ │ │ ├─image6.png + │ │ │ └─... + │ │ └─TarotImages + │ │ ├─image7.png + │ │ └─... + │ └─who_say + │ ├─image8.png + │ └─... + ├─log + │ ├─bot.log + │ └─... + ├─temp + │ ├─temp_file1.tmp + │ └─... + └─videos + ├─video1.mp4 + └─... +``` + + +### 详细说明 + +- **根目录文件** + - `.gitignore`: 忽略文件配置。 + - `bot.py`: 机器人启动文件。 + - `chat_bot.db`: SQLite 数据库文件。 + - `example.env.prod`: 示例环境配置文件。 + - `package-lock.json`: npm 依赖锁定文件。 + - `package.json`: npm 依赖配置文件。 + - `pyproject.toml`: Python 项目配置文件。 + - `README.md`: 项目说明文档。 + - `requirements.txt`: Python 依赖配置文件。 + +- **node_modules** + - `crypto-js`: 加密库。 + +- **src 目录** + - **clover_image** + - `get_image.py`: 图片获取模块。 + + - **clover_music** + - **cloud_music** + - `cloud_music_cookies.cookie`: 网易云音乐 cookie 文件。 + - `qrcode.png`: 网易云音乐扫码登录二维码。 + - **netease_music** + - 网易云音乐相关模块。 + + - **clover_openai** + - `api_config_example.py`: 示例 API 配置文件。 + - `api_config.py`: 实际 API 配置文件。 + + - **clover_sqlite** + - **data_init** + - `init_tables.py`: 数据库初始化脚本。 + - 其他初始化脚本。 + - **models** + - `models.py`: 数据库模型定义。 + - 其他模型定义文件。 + + - **clover_videos** + - **bilibili** + - `bilibili_search.py`: B站视频搜索模块。 + - 其他 B站相关模块。 + + - **configs** + - `path_config.py`: 路径配置文件。 + - `api_config_example.py`: 示例 API 配置文件。 + - **utils** + - `utils.py`: 工具函数。 + - 其他工具函数文件。 + + - **plugins** + - `check.py`: 指令检查模块。 + - `todo.py`: 待办事项模块。 + - `weather.py`: 天气模块。 + - `fortune.py`: 运势模块。 + - `tarot.py`: 塔罗牌模块。 + - `music.py`: 点歌模块。 + - `image.py`: 图片模块。 + - `petpet.py`: 摸摸头模块。 + - `openai.py`: AI 模块。 + - `bilibili.py`: B站视频模块。 + - `news.py`: 日报模块。 + - `light_novel.py`: 轻小说模块。 + - `anime.py`: 新番信息模块。 + - 其他插件模块。 + + - **resources** + - **font** + - `font.ttf`: 字体文件。 + - 其他字体文件。 + - **image** + - **codeforces** + - `image1.png`: 图片文件。 + - 其他图片文件。 + - **github_repo** + - `image2.png`: 图片文件。 + - 其他图片文件。 + - **good_bad_news** + - `image3.png`: 图片文件。 + - 其他图片文件。 + - **MaoYuNa** + - `image4.png`: 图片文件。 + - 其他图片文件。 + - **rua** + - `image5.png`: 图片文件。 + - 其他图片文件。 + - **tarot** + - **sideTarotImages** + - `image6.png`: 图片文件。 + - 其他图片文件。 + - **TarotImages** + - `image7.png`: 图片文件。 + - 其他图片文件。 + - **who_say** + - `image8.png`: 图片文件。 + - 其他图片文件。 + - **log** + - `bot.log`: 日志文件。 + - 其他日志文件。 + - **temp** + - `temp_file1.tmp`: 临时文件。 + - 其他临时文件。 + - **videos** + - `video1.mp4`: 视频文件。 + - 其他视频文件。 + +
+### 📦三、插件 + - 插件的目录位于src/plugins中
+ - 插件的配置文件位于src/configs中
+ - 基本插件存储在plugins目录中,启动即可使用
+ - 部分插件通过调用其它目录中的方法完成其功能
+ - 部分插件需要调用第三方API,需要在配置文件中填写相关配置
+ +
+ +### 🎈四、更多功能 + +#### 📲所有指令 + +机器人的指令列表在[src/plugins/check.py](src/plugins/check.py)中,有如下指令: + +```python +menu = ["/重启","/今日运势","/今日塔罗","/图","/日报","/点歌","/摸摸头","/群老婆","/今日老婆", "/开启ai","/关闭ai", + "/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册","/待办", "/test","/天气", + "我喜欢你", "❤", "/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报", + "/luxun","/鲁迅说", "/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/新番观察"] +``` + +输入其它指令机器人会回复听不懂哦。 + +
+ + + +### 🎨 功能补充说明 + +#### 📄 需要替换的文件 + +首先找到 [**src/configs/api_config_example.py**](src/configs/api_config_example.py) 文件,并根据需要替换以下配置项: + +```python +app_id = "" +bot_account = "" + +""" +图床配置 +""" +# SMMS图床相关配置 +smms_token = "" # sm.ms图床的token +smms_image_upload_history = "https://sm.ms/api/v2/upload_history" # sm.ms图床获取上传图片历史API地址 + +# 聚合图床相关配置 +ju_he_token = "" # 聚合图床的token +ju_he_image_list = "https://api.superbed.cn/timeline" # 聚合图床获取上传图片历史API地址 + +""" +AI +""" +admin_password = "123456" # 默认注册管理员密码 +# 图灵机器人相关配置 +v3url = "https://api.vveai.com/v1/chat/completions" +v3key = "" +# DeepSeek相关配置 +deepseek_url = "https://api.deepseek.com" +deepseek_key = "" + +""" +Wenku8账号 +""" +wenku8_username = "" +wenku8_password = "" + +""" +多米HTTP代理api +""" +proxy_api = "" +``` + + +将你的 `app_id` 和 `smms_token` 替换为实际值(可以根据自身需求选填),然后将文件重命名为 **api_config.py**。 + +
+ +#### 🎵 使用网易云API实现点歌 + +若您是初次使用点歌功能,在群聊中 @ 机器人后,机器人会提示: + +``` +登录失效,请联系管理员进行登录 +``` + + +此时会在 [**src/music**](src/clover_music) 目录下生成一张 **qrcode.png**,您需要使用手机端网易云音乐扫码该二维码,登录您的网易云账号。 + +注意: 我们使用 cookie 存储用户登录信息,所以会存在登录过期的情况。若 cookie 过期,机器人会提示: + +``` +歌曲音频获取失败:登录信息失效。 +``` + + +此时需要 **删除** [**cloud_music_cookies.cookie**](cloud_music_cookies.cookie) 并重新扫码登录。 + +
+ +#### ✋ 管理员身份认证 + +##### 介绍 + +机器人现已更新管理员机制,机器人管理员可以控制是否使用第三方大语言模型进行交互。后续其它功能更新中。 + +##### 使用 + +###### 1. 注册为管理员 + +在 [**src/configs/api_config_example.py**](src/configs/api_config_example.py) 内,找到: + +```python +admin_password = "123456" # 默认注册管理员密码 +``` + + +可以更改为自己的密码。 + +设置好密码后,在 QQ 中 at 你的机器人,格式为: + +``` +@<机器人名称> /管理员注册 <密码> +``` + + +例如,对三叶草进行管理员注册时,假如密码是 123456,需要: + +``` +@三叶草 /管理员注册 123456 +``` + + +注意: 管理员密码请不要泄露给其他人,建议定期更换密码。 + +注册成为管理员之后,你的 `member_openid` 将会被保存至 `chatbot.db` 下的 `admin_list` 表中。 + +希望这些优化后的说明能更好地帮助您!如果有任何进一步的需求或修改,请告诉我。 + + + diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..bdfd08f --- /dev/null +++ b/bot.py @@ -0,0 +1,18 @@ +import nonebot +from nonebot.adapters.qq import Adapter as QQAdapter +from nonebot import logger +from nonebot.log import default_format, default_filter + +nonebot.init() +driver = nonebot.get_driver() +driver.register_adapter(QQAdapter) # 注册QQ适配器 +nonebot.load_from_toml("pyproject.toml") +logger.add("src/resources/log/error.log", level="ERROR", format=default_format, rotation="1 week") + +from src.clover_sqlite.data_init.db_connect import disconnect, init +driver.on_startup(init) +driver.on_shutdown(disconnect) + + +if __name__ == "__main__": + nonebot.run() diff --git a/example.env.prod b/example.env.prod new file mode 100644 index 0000000..63d9335 --- /dev/null +++ b/example.env.prod @@ -0,0 +1,15 @@ +DRIVER=~fastapi+~httpx+~websockets + +QQ_BOTS=' +[ + { + "id": "xxx", + "token": "xxx", + "secret": "xxx", + "intent": { + "c2c_group_at_messages": true + }, + "use_websocket": true + } +] +' \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..3d63310 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "SanYeCao-Nonebot", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + } + } +} diff --git a/node_modules/crypto-js/CONTRIBUTING.md b/node_modules/crypto-js/CONTRIBUTING.md new file mode 100644 index 0000000..09bf774 --- /dev/null +++ b/node_modules/crypto-js/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contribution + +# Git Flow + +The crypto-js project uses [git flow](https://github.com/nvie/gitflow) to manage branches. +Do your changes on the `develop` or even better on a `feature/*` branch. Don't do any changes on the `master` branch. + +# Pull request + +Target your pull request on `develop` branch. Other pull request won't be accepted. + +# How to build + +1. Clone + +2. Run + + ```sh + npm install + ``` + +3. Run + + ```sh + npm run build + ``` + +4. Check `build` folder \ No newline at end of file diff --git a/node_modules/crypto-js/LICENSE b/node_modules/crypto-js/LICENSE new file mode 100644 index 0000000..b0828e5 --- /dev/null +++ b/node_modules/crypto-js/LICENSE @@ -0,0 +1,24 @@ +# License + +[The MIT License (MIT)](http://opensource.org/licenses/MIT) + +Copyright (c) 2009-2013 Jeff Mott +Copyright (c) 2013-2016 Evan Vosberg + +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/node_modules/crypto-js/README.md b/node_modules/crypto-js/README.md new file mode 100644 index 0000000..6a9bcdf --- /dev/null +++ b/node_modules/crypto-js/README.md @@ -0,0 +1,275 @@ +# crypto-js + +JavaScript library of crypto standards. + +## Discontinued + +Active development of CryptoJS has been discontinued. This library is no longer maintained. + +Nowadays, NodeJS and modern browsers have a native `Crypto` module. The latest version of CryptoJS already uses the native Crypto module for random number generation, since `Math.random()` is not crypto-safe. Further development of CryptoJS would result in it only being a wrapper of native Crypto. Therefore, development and maintenance has been discontinued, it is time to go for the native `crypto` module. + +## Node.js (Install) + +Requirements: + +- Node.js +- npm (Node.js package manager) + +```bash +npm install crypto-js +``` + +### Usage + +ES6 import for typical API call signing use case: + +```javascript +import sha256 from 'crypto-js/sha256'; +import hmacSHA512 from 'crypto-js/hmac-sha512'; +import Base64 from 'crypto-js/enc-base64'; + +const message, nonce, path, privateKey; // ... +const hashDigest = sha256(nonce + message); +const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey)); +``` + +Modular include: + +```javascript +var AES = require("crypto-js/aes"); +var SHA256 = require("crypto-js/sha256"); +... +console.log(SHA256("Message")); +``` + +Including all libraries, for access to extra methods: + +```javascript +var CryptoJS = require("crypto-js"); +console.log(CryptoJS.HmacSHA1("Message", "Key")); +``` + +## Client (browser) + +Requirements: + +- Node.js +- Bower (package manager for frontend) + +```bash +bower install crypto-js +``` + +### Usage + +Modular include: + +```javascript +require.config({ + packages: [ + { + name: 'crypto-js', + location: 'path-to/bower_components/crypto-js', + main: 'index' + } + ] +}); + +require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) { + console.log(SHA256("Message")); +}); +``` + +Including all libraries, for access to extra methods: + +```javascript +// Above-mentioned will work or use this simple form +require.config({ + paths: { + 'crypto-js': 'path-to/bower_components/crypto-js/crypto-js' + } +}); + +require(["crypto-js"], function (CryptoJS) { + console.log(CryptoJS.HmacSHA1("Message", "Key")); +}); +``` + +### Usage without RequireJS + +```html + + +``` + +## API + +See: https://cryptojs.gitbook.io/docs/ + +### AES Encryption + +#### Plain text encryption + +```javascript +var CryptoJS = require("crypto-js"); + +// Encrypt +var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString(); + +// Decrypt +var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123'); +var originalText = bytes.toString(CryptoJS.enc.Utf8); + +console.log(originalText); // 'my message' +``` + +#### Object encryption + +```javascript +var CryptoJS = require("crypto-js"); + +var data = [{id: 1}, {id: 2}] + +// Encrypt +var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString(); + +// Decrypt +var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123'); +var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); + +console.log(decryptedData); // [{id: 1}, {id: 2}] +``` + +### List of modules + + +- ```crypto-js/core``` +- ```crypto-js/x64-core``` +- ```crypto-js/lib-typedarrays``` + +--- + +- ```crypto-js/md5``` +- ```crypto-js/sha1``` +- ```crypto-js/sha256``` +- ```crypto-js/sha224``` +- ```crypto-js/sha512``` +- ```crypto-js/sha384``` +- ```crypto-js/sha3``` +- ```crypto-js/ripemd160``` + +--- + +- ```crypto-js/hmac-md5``` +- ```crypto-js/hmac-sha1``` +- ```crypto-js/hmac-sha256``` +- ```crypto-js/hmac-sha224``` +- ```crypto-js/hmac-sha512``` +- ```crypto-js/hmac-sha384``` +- ```crypto-js/hmac-sha3``` +- ```crypto-js/hmac-ripemd160``` + +--- + +- ```crypto-js/pbkdf2``` + +--- + +- ```crypto-js/aes``` +- ```crypto-js/tripledes``` +- ```crypto-js/rc4``` +- ```crypto-js/rabbit``` +- ```crypto-js/rabbit-legacy``` +- ```crypto-js/evpkdf``` + +--- + +- ```crypto-js/format-openssl``` +- ```crypto-js/format-hex``` + +--- + +- ```crypto-js/enc-latin1``` +- ```crypto-js/enc-utf8``` +- ```crypto-js/enc-hex``` +- ```crypto-js/enc-utf16``` +- ```crypto-js/enc-base64``` + +--- + +- ```crypto-js/mode-cfb``` +- ```crypto-js/mode-ctr``` +- ```crypto-js/mode-ctr-gladman``` +- ```crypto-js/mode-ofb``` +- ```crypto-js/mode-ecb``` + +--- + +- ```crypto-js/pad-pkcs7``` +- ```crypto-js/pad-ansix923``` +- ```crypto-js/pad-iso10126``` +- ```crypto-js/pad-iso97971``` +- ```crypto-js/pad-zeropadding``` +- ```crypto-js/pad-nopadding``` + + +## Release notes + +### 4.2.0 + +Change default hash algorithm and iteration's for PBKDF2 to prevent weak security by using the default configuration. + +Custom KDF Hasher + +Blowfish support + +### 4.1.1 + +Fix module order in bundled release. + +Include the browser field in the released package.json. + +### 4.1.0 + +Added url safe variant of base64 encoding. [357](https://github.com/brix/crypto-js/pull/357) + +Avoid webpack to add crypto-browser package. [364](https://github.com/brix/crypto-js/pull/364) + +### 4.0.0 + +This is an update including breaking changes for some environments. + +In this version `Math.random()` has been replaced by the random methods of the native crypto module. + +For this reason CryptoJS might not run in some JavaScript environments without native crypto module. Such as IE 10 or before or React Native. + +### 3.3.0 + +Rollback, `3.3.0` is the same as `3.1.9-1`. + +The move of using native secure crypto module will be shifted to a new `4.x.x` version. As it is a breaking change the impact is too big for a minor release. + +### 3.2.1 + +The usage of the native crypto module has been fixed. The import and access of the native crypto module has been improved. + +### 3.2.0 + +In this version `Math.random()` has been replaced by the random methods of the native crypto module. + +For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before. + +If it's absolute required to run CryptoJS in such an environment, stay with `3.1.x` version. Encrypting and decrypting stays compatible. But keep in mind `3.1.x` versions still use `Math.random()` which is cryptographically not secure, as it's not random enough. + +This version came along with `CRITICAL` `BUG`. + +DO NOT USE THIS VERSION! Please, go for a newer version! + +### 3.1.x + +The `3.1.x` are based on the original CryptoJS, wrapped in CommonJS modules. + + diff --git a/node_modules/crypto-js/aes.js b/node_modules/crypto-js/aes.js new file mode 100644 index 0000000..166e3ea --- /dev/null +++ b/node_modules/crypto-js/aes.js @@ -0,0 +1,234 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + var t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6; + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + return CryptoJS.AES; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/blowfish.js b/node_modules/crypto-js/blowfish.js new file mode 100644 index 0000000..149812f --- /dev/null +++ b/node_modules/crypto-js/blowfish.js @@ -0,0 +1,471 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + const N = 16; + + //Origin pbox and sbox, derived from PI + const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B + ]; + + const ORIG_S = [ + [ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A ], + [ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 ], + [ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 ], + [ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 ] + ]; + + var BLOWFISH_CTX = { + pbox: [], + sbox: [] + } + + function F(ctx, x){ + let a = (x >> 24) & 0xFF; + let b = (x >> 16) & 0xFF; + let c = (x >> 8) & 0xFF; + let d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; + } + + function BlowFish_Encrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; + } + + function BlowFish_Decrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; + } + + /** + * Initialization ctx's pbox and sbox. + * + * @param {Object} ctx The object has pbox and sbox. + * @param {Array} key An array of 32-bit words. + * @param {int} keysize The length of the key. + * + * @example + * + * BlowFishInit(BLOWFISH_CTX, key, 128/32); + */ + function BlowFishInit(ctx, key, keysize) + { + for(let Row = 0; Row < 4; Row++) + { + ctx.sbox[Row] = []; + for(let Col = 0; Col < 256; Col++) + { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for(let index = 0; index < N + 2; index++) + { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if(keyIndex >= keysize) + { + keyIndex = 0; + } + } + + let Data1 = 0; + let Data2 = 0; + let res = 0; + for(let i = 0; i < N + 2; i += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.pbox[i] = Data1; + ctx.pbox[i + 1] = Data2; + } + + for(let i = 0; i < 4; i++) + { + for(let j = 0; j < 256; j += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.sbox[i][j] = Data1; + ctx.sbox[i][j + 1] = Data2; + } + } + + return true; + } + + /** + * Blowfish block cipher algorithm. + */ + var Blowfish = C_algo.Blowfish = BlockCipher.extend({ + _doReset: function () { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + BlowFishInit(BLOWFISH_CTX, keyWords, keySize); + }, + + encryptBlock: function (M, offset) { + var res = BlowFish_Encrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + decryptBlock: function (M, offset) { + var res = BlowFish_Decrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + blockSize: 64/32, + + keySize: 128/32, + + ivSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ + C.Blowfish = BlockCipher._createHelper(Blowfish); + }()); + + + return CryptoJS.Blowfish; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/bower.json b/node_modules/crypto-js/bower.json new file mode 100644 index 0000000..4dee617 --- /dev/null +++ b/node_modules/crypto-js/bower.json @@ -0,0 +1,39 @@ +{ + "name": "crypto-js", + "version": "4.2.0", + "description": "JavaScript library of crypto standards.", + "license": "MIT", + "homepage": "http://github.com/brix/crypto-js", + "repository": { + "type": "git", + "url": "http://github.com/brix/crypto-js.git" + }, + "keywords": [ + "security", + "crypto", + "Hash", + "MD5", + "SHA1", + "SHA-1", + "SHA256", + "SHA-256", + "RC4", + "Rabbit", + "AES", + "DES", + "PBKDF2", + "HMAC", + "OFB", + "CFB", + "CTR", + "CBC", + "Base64", + "Base64url" + ], + "main": "index.js", + "dependencies": {}, + "browser": { + "crypto": false + }, + "ignore": [] +} diff --git a/node_modules/crypto-js/cipher-core.js b/node_modules/crypto-js/cipher-core.js new file mode 100644 index 0000000..903f462 --- /dev/null +++ b/node_modules/crypto-js/cipher-core.js @@ -0,0 +1,895 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./evpkdf")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./evpkdf"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + var block; + + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + var modeCreator; + + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + if (this._mode && this._mode.__creator == modeCreator) { + this._mode.init(this, iv && iv.words); + } else { + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + var finalProcessedBlocks; + + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + var wordArray; + + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + var salt; + + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt, hasher) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + if (!hasher) { + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + } else { + var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt); + } + + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/core.js b/node_modules/crypto-js/core.js new file mode 100644 index 0000000..e3a498b --- /dev/null +++ b/node_modules/crypto-js/core.js @@ -0,0 +1,807 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /*globals window, global, require*/ + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + + var crypto; + + // Native crypto from window (Browser) + if (typeof window !== 'undefined' && window.crypto) { + crypto = window.crypto; + } + + // Native crypto in web worker (Browser) + if (typeof self !== 'undefined' && self.crypto) { + crypto = self.crypto; + } + + // Native crypto from worker + if (typeof globalThis !== 'undefined' && globalThis.crypto) { + crypto = globalThis.crypto; + } + + // Native (experimental IE 11) crypto from window (Browser) + if (!crypto && typeof window !== 'undefined' && window.msCrypto) { + crypto = window.msCrypto; + } + + // Native crypto from global (NodeJS) + if (!crypto && typeof global !== 'undefined' && global.crypto) { + crypto = global.crypto; + } + + // Native crypto import via require (NodeJS) + if (!crypto && typeof require === 'function') { + try { + crypto = require('crypto'); + } catch (err) {} + } + + /* + * Cryptographically secure pseudorandom number generator + * + * As Math.random() is cryptographically not safe to use + */ + var cryptoSecureRandomInt = function () { + if (crypto) { + // Use getRandomValues method (Browser) + if (typeof crypto.getRandomValues === 'function') { + try { + return crypto.getRandomValues(new Uint32Array(1))[0]; + } catch (err) {} + } + + // Use randomBytes method (NodeJS) + if (typeof crypto.randomBytes === 'function') { + try { + return crypto.randomBytes(4).readInt32LE(); + } catch (err) {} + } + } + + throw new Error('Native crypto module could not be used to get secure random number.'); + }; + + /* + * Local polyfill of Object.create + + */ + var create = Object.create || (function () { + function F() {} + + return function (obj) { + var subtype; + + F.prototype = obj; + + subtype = new F(); + + F.prototype = null; + + return subtype; + }; + }()); + + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + var subtype = create(this); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init') || this.init === subtype.init) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var j = 0; j < thatSigBytes; j += 4) { + thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + for (var i = 0; i < nBytes; i += 4) { + words.push(cryptoSecureRandomInt()); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + var processedWords; + + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/crypto-js.js b/node_modules/crypto-js/crypto-js.js new file mode 100644 index 0000000..958ee53 --- /dev/null +++ b/node_modules/crypto-js/crypto-js.js @@ -0,0 +1,6657 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /*globals window, global, require*/ + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + + var crypto; + + // Native crypto from window (Browser) + if (typeof window !== 'undefined' && window.crypto) { + crypto = window.crypto; + } + + // Native crypto in web worker (Browser) + if (typeof self !== 'undefined' && self.crypto) { + crypto = self.crypto; + } + + // Native crypto from worker + if (typeof globalThis !== 'undefined' && globalThis.crypto) { + crypto = globalThis.crypto; + } + + // Native (experimental IE 11) crypto from window (Browser) + if (!crypto && typeof window !== 'undefined' && window.msCrypto) { + crypto = window.msCrypto; + } + + // Native crypto from global (NodeJS) + if (!crypto && typeof global !== 'undefined' && global.crypto) { + crypto = global.crypto; + } + + // Native crypto import via require (NodeJS) + if (!crypto && typeof require === 'function') { + try { + crypto = require('crypto'); + } catch (err) {} + } + + /* + * Cryptographically secure pseudorandom number generator + * + * As Math.random() is cryptographically not safe to use + */ + var cryptoSecureRandomInt = function () { + if (crypto) { + // Use getRandomValues method (Browser) + if (typeof crypto.getRandomValues === 'function') { + try { + return crypto.getRandomValues(new Uint32Array(1))[0]; + } catch (err) {} + } + + // Use randomBytes method (NodeJS) + if (typeof crypto.randomBytes === 'function') { + try { + return crypto.randomBytes(4).readInt32LE(); + } catch (err) {} + } + } + + throw new Error('Native crypto module could not be used to get secure random number.'); + }; + + /* + * Local polyfill of Object.create + + */ + var create = Object.create || (function () { + function F() {} + + return function (obj) { + var subtype; + + F.prototype = obj; + + subtype = new F(); + + F.prototype = null; + + return subtype; + }; + }()); + + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + var subtype = create(this); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init') || this.init === subtype.init) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var j = 0; j < thatSigBytes; j += 4) { + thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + for (var i = 0; i < nBytes; i += 4) { + words.push(cryptoSecureRandomInt()); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + var processedWords; + + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var X32WordArray = C_lib.WordArray; + + /** + * x64 namespace. + */ + var C_x64 = C.x64 = {}; + + /** + * A 64-bit word. + */ + var X64Word = C_x64.Word = Base.extend({ + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + init: function (high, low) { + this.high = high; + this.low = low; + } + + /** + * Bitwise NOTs this word. + * + * @return {X64Word} A new x64-Word object after negating. + * + * @example + * + * var negated = x64Word.not(); + */ + // not: function () { + // var high = ~this.high; + // var low = ~this.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ANDs this word with the passed word. + * + * @param {X64Word} word The x64-Word to AND with this word. + * + * @return {X64Word} A new x64-Word object after ANDing. + * + * @example + * + * var anded = x64Word.and(anotherX64Word); + */ + // and: function (word) { + // var high = this.high & word.high; + // var low = this.low & word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to OR with this word. + * + * @return {X64Word} A new x64-Word object after ORing. + * + * @example + * + * var ored = x64Word.or(anotherX64Word); + */ + // or: function (word) { + // var high = this.high | word.high; + // var low = this.low | word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise XORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to XOR with this word. + * + * @return {X64Word} A new x64-Word object after XORing. + * + * @example + * + * var xored = x64Word.xor(anotherX64Word); + */ + // xor: function (word) { + // var high = this.high ^ word.high; + // var low = this.low ^ word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the left. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftL(25); + */ + // shiftL: function (n) { + // if (n < 32) { + // var high = (this.high << n) | (this.low >>> (32 - n)); + // var low = this.low << n; + // } else { + // var high = this.low << (n - 32); + // var low = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the right. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftR(7); + */ + // shiftR: function (n) { + // if (n < 32) { + // var low = (this.low >>> n) | (this.high << (32 - n)); + // var high = this.high >>> n; + // } else { + // var low = this.high >>> (n - 32); + // var high = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Rotates this word n bits to the left. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotL(25); + */ + // rotL: function (n) { + // return this.shiftL(n).or(this.shiftR(64 - n)); + // }, + + /** + * Rotates this word n bits to the right. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotR(7); + */ + // rotR: function (n) { + // return this.shiftR(n).or(this.shiftL(64 - n)); + // }, + + /** + * Adds this word with the passed word. + * + * @param {X64Word} word The x64-Word to add with this word. + * + * @return {X64Word} A new x64-Word object after adding. + * + * @example + * + * var added = x64Word.add(anotherX64Word); + */ + // add: function (word) { + // var low = (this.low + word.low) | 0; + // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; + // var high = (this.high + word.high + carry) | 0; + + // return X64Word.create(high, low); + // } + }); + + /** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var X64WordArray = C_x64.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 8; + } + }, + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32: function () { + // Shortcuts + var x64Words = this.words; + var x64WordsLength = x64Words.length; + + // Convert + var x32Words = []; + for (var i = 0; i < x64WordsLength; i++) { + var x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + }, + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + + // Clone "words" array + var words = clone.words = this.words.slice(0); + + // Clone each X64Word object + var wordsLength = words.length; + for (var i = 0; i < wordsLength; i++) { + words[i] = words[i].clone(); + } + + return clone; + } + }); + }()); + + + (function () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * UTF-16 BE encoding strategy. + */ + var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + /** + * UTF-16 LE encoding strategy. + */ + C_enc.Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + function swapEndian(word) { + return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + } + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64url encoding strategy. + */ + var Base64url = C_enc.Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64url.stringify(wordArray); + */ + stringify: function (wordArray, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = urlSafe ? this._safe_map : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64url.parse(base64String); + */ + parse: function (base64Str, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + + // Shortcuts + var base64StrLength = base64Str.length; + var map = urlSafe ? this._safe_map : this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + _safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + + /** + * SHA-224 hash algorithm. + */ + var SHA224 = C_algo.SHA224 = SHA256.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]); + }, + + _doFinalize: function () { + var hash = SHA256._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ + C.SHA224 = SHA256._createHelper(SHA224); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ + C.HmacSHA224 = SHA256._createHmacHelper(SHA224); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + + function X64Word_create() { + return X64Word.create.apply(X64Word, arguments); + } + + // Constants + var K = [ + X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), + X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), + X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), + X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), + X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), + X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), + X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), + X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), + X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), + X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), + X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), + X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), + X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), + X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), + X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), + X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), + X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), + X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), + X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), + X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), + X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), + X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), + X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), + X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), + X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), + X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), + X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), + X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), + X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), + X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), + X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), + X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), + X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), + X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), + X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), + X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), + X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), + X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), + X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), + X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) + ]; + + // Reusable objects + var W = []; + (function () { + for (var i = 0; i < 80; i++) { + W[i] = X64Word_create(); + } + }()); + + /** + * SHA-512 hash algorithm. + */ + var SHA512 = C_algo.SHA512 = Hasher.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), + new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), + new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), + new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var H = this._hash.words; + + var H0 = H[0]; + var H1 = H[1]; + var H2 = H[2]; + var H3 = H[3]; + var H4 = H[4]; + var H5 = H[5]; + var H6 = H[6]; + var H7 = H[7]; + + var H0h = H0.high; + var H0l = H0.low; + var H1h = H1.high; + var H1l = H1.low; + var H2h = H2.high; + var H2l = H2.low; + var H3h = H3.high; + var H3l = H3.low; + var H4h = H4.high; + var H4l = H4.low; + var H5h = H5.high; + var H5l = H5.low; + var H6h = H6.high; + var H6l = H6.low; + var H7h = H7.high; + var H7l = H7.low; + + // Working variables + var ah = H0h; + var al = H0l; + var bh = H1h; + var bl = H1l; + var ch = H2h; + var cl = H2l; + var dh = H3h; + var dl = H3l; + var eh = H4h; + var el = H4l; + var fh = H5h; + var fl = H5l; + var gh = H6h; + var gl = H6l; + var hh = H7h; + var hl = H7l; + + // Rounds + for (var i = 0; i < 80; i++) { + var Wil; + var Wih; + + // Shortcut + var Wi = W[i]; + + // Extend message + if (i < 16) { + Wih = Wi.high = M[offset + i * 2] | 0; + Wil = Wi.low = M[offset + i * 2 + 1] | 0; + } else { + // Gamma0 + var gamma0x = W[i - 15]; + var gamma0xh = gamma0x.high; + var gamma0xl = gamma0x.low; + var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); + var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + var gamma1x = W[i - 2]; + var gamma1xh = gamma1x.high; + var gamma1xl = gamma1x.low; + var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); + var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7 = W[i - 7]; + var Wi7h = Wi7.high; + var Wi7l = Wi7.low; + + var Wi16 = W[i - 16]; + var Wi16h = Wi16.high; + var Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil = Wil + gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil = Wil + Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + var chh = (eh & fh) ^ (~eh & gh); + var chl = (el & fl) ^ (~el & gl); + var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + var majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); + var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); + var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); + var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + var Ki = K[i]; + var Kih = Ki.high; + var Kil = Ki.low; + + var t1l = hl + sigma1l; + var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + var t1l = t1l + chl; + var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + var t1l = t1l + Kil; + var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + var t1l = t1l + Wil; + var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + var t2l = sigma0l + majl; + var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0l = H0.low = (H0l + al); + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1l = H1.low = (H1l + bl); + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2l = H2.low = (H2l + cl); + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3l = H3.low = (H3l + dl); + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4l = H4.low = (H4l + el); + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5l = H5.low = (H5l + fl); + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6l = H6.low = (H6l + gl); + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7l = H7.low = (H7l + hl); + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + var hash = this._hash.toX32(); + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + }, + + blockSize: 1024/32 + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ + C.SHA512 = Hasher._createHelper(SHA512); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ + C.HmacSHA512 = Hasher._createHmacHelper(SHA512); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + var SHA512 = C_algo.SHA512; + + /** + * SHA-384 hash algorithm. + */ + var SHA384 = C_algo.SHA384 = SHA512.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), + new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), + new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), + new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) + ]); + }, + + _doFinalize: function () { + var hash = SHA512._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ + C.SHA384 = SHA512._createHelper(SHA384); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ + C.HmacSHA384 = SHA512._createHmacHelper(SHA384); + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var C_algo = C.algo; + + // Constants tables + var RHO_OFFSETS = []; + var PI_INDEXES = []; + var ROUND_CONSTANTS = []; + + // Compute Constants + (function () { + // Compute rho offset constants + var x = 1, y = 0; + for (var t = 0; t < 24; t++) { + RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; + + var newX = y % 5; + var newY = (2 * x + 3 * y) % 5; + x = newX; + y = newY; + } + + // Compute pi index constants + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } + } + + // Compute round constants + var LFSR = 0x01; + for (var i = 0; i < 24; i++) { + var roundConstantMsw = 0; + var roundConstantLsw = 0; + + for (var j = 0; j < 7; j++) { + if (LFSR & 0x01) { + var bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); + } + }()); + + // Reusable objects for temporary values + var T = []; + (function () { + for (var i = 0; i < 25; i++) { + T[i] = X64Word.create(); + } + }()); + + /** + * SHA-3 hash algorithm. + */ + var SHA3 = C_algo.SHA3 = Hasher.extend({ + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + cfg: Hasher.cfg.extend({ + outputLength: 512 + }), + + _doReset: function () { + var state = this._state = [] + for (var i = 0; i < 25; i++) { + state[i] = new X64Word.init(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var state = this._state; + var nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (var i = 0; i < nBlockSizeLanes; i++) { + // Shortcuts + var M2i = M[offset + 2 * i]; + var M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = ( + (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | + (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) + ); + M2i1 = ( + (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | + (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) + ); + + // Absorb message into state + var lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (var round = 0; round < 24; round++) { + // Theta + for (var x = 0; x < 5; x++) { + // Mix column lanes + var tMsw = 0, tLsw = 0; + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + var Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (var x = 0; x < 5; x++) { + // Shortcuts + var Tx4 = T[(x + 4) % 5]; + var Tx1 = T[(x + 1) % 5]; + var Tx1Msw = Tx1.high; + var Tx1Lsw = Tx1.low; + + // Mix surrounding columns + var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (var laneIndex = 1; laneIndex < 25; laneIndex++) { + var tMsw; + var tLsw; + + // Shortcuts + var lane = state[laneIndex]; + var laneMsw = lane.high; + var laneLsw = lane.low; + var rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + var TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + var T0 = T[0]; + var state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + // Shortcuts + var laneIndex = x + 5 * y; + var lane = state[laneIndex]; + var TLane = T[laneIndex]; + var Tx1Lane = T[((x + 1) % 5) + 5 * y]; + var Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + var lane = state[0]; + var roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + var blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var state = this._state; + var outputLengthBytes = this.cfg.outputLength / 8; + var outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + var hashWords = []; + for (var i = 0; i < outputLengthLanes; i++) { + // Shortcuts + var lane = state[i]; + var laneMsw = lane.high; + var laneLsw = lane.low; + + // Swap endian + laneMsw = ( + (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | + (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) + ); + laneLsw = ( + (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | + (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) + ); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray.init(hashWords, outputLengthBytes); + }, + + clone: function () { + var clone = Hasher.clone.call(this); + + var state = clone._state = this._state.slice(0); + for (var i = 0; i < 25; i++) { + state[i] = state[i].clone(); + } + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ + C.SHA3 = Hasher._createHelper(SHA3); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ + C.HmacSHA3 = Hasher._createHmacHelper(SHA3); + }(Math)); + + + /** @preserve + (c) 2012 by Cédric Mesnil. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. + */ + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); + var _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); + var _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); + var _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); + + var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); + var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + + /** + * RIPEMD160 hash algorithm. + */ + var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ + _doReset: function () { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + }, + + _doProcessBlock: function (M, offset) { + + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + // Swap + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + var H = this._hash.words; + var hl = _hl.words; + var hr = _hr.words; + var zl = _zl.words; + var zr = _zr.words; + var sl = _sl.words; + var sr = _sr.words; + + // Working variables + var al, bl, cl, dl, el; + var ar, br, cr, dr, er; + + ar = al = H[0]; + br = bl = H[1]; + cr = cl = H[2]; + dr = dl = H[3]; + er = el = H[4]; + // Computation + var t; + for (var i = 0; i < 80; i += 1) { + t = (al + M[offset+zl[i]])|0; + if (i<16){ + t += f1(bl,cl,dl) + hl[0]; + } else if (i<32) { + t += f2(bl,cl,dl) + hl[1]; + } else if (i<48) { + t += f3(bl,cl,dl) + hl[2]; + } else if (i<64) { + t += f4(bl,cl,dl) + hl[3]; + } else {// if (i<80) { + t += f5(bl,cl,dl) + hl[4]; + } + t = t|0; + t = rotl(t,sl[i]); + t = (t+el)|0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + M[offset+zr[i]])|0; + if (i<16){ + t += f5(br,cr,dr) + hr[0]; + } else if (i<32) { + t += f4(br,cr,dr) + hr[1]; + } else if (i<48) { + t += f3(br,cr,dr) + hr[2]; + } else if (i<64) { + t += f2(br,cr,dr) + hr[3]; + } else {// if (i<80) { + t += f1(br,cr,dr) + hr[4]; + } + t = t|0; + t = rotl(t,sr[i]) ; + t = (t+er)|0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr)|0; + H[1] = (H[2] + dl + er)|0; + H[2] = (H[3] + el + ar)|0; + H[3] = (H[4] + al + br)|0; + H[4] = (H[0] + bl + cr)|0; + H[0] = t; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | + (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 5; i++) { + // Shortcut + var H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + + function f1(x, y, z) { + return ((x) ^ (y) ^ (z)); + + } + + function f2(x, y, z) { + return (((x)&(y)) | ((~x)&(z))); + } + + function f3(x, y, z) { + return (((x) | (~(y))) ^ (z)); + } + + function f4(x, y, z) { + return (((x) & (z)) | ((y)&(~(z)))); + } + + function f5(x, y, z) { + return ((x) ^ ((y) |(~(z)))); + + } + + function rotl(x,n) { + return (x<>>(32-n)); + } + + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ + C.RIPEMD160 = Hasher._createHelper(RIPEMD160); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ + C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + var HMAC = C_algo.HMAC; + + /** + * Password-Based Key Derivation Function 2 algorithm. + */ + var PBKDF2 = C_algo.PBKDF2 = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: SHA256, + iterations: 250000 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.PBKDF2.create(); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init HMAC + var hmac = HMAC.create(cfg.hasher, password); + + // Initial values + var derivedKey = WordArray.create(); + var blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var blockIndexWords = blockIndex.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + var block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + var blockWords = block.words; + var blockWordsLength = blockWords.length; + + // Iterations + var intermediate = block; + for (var i = 1; i < iterations; i++) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + var intermediateWords = intermediate.words; + + // XOR intermediate with block + for (var j = 0; j < blockWordsLength; j++) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0]++; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.PBKDF2 = function (password, salt, cfg) { + return PBKDF2.create(cfg).compute(password, salt); + }; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + var block; + + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + var block; + + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + var modeCreator; + + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + if (this._mode && this._mode.__creator == modeCreator) { + this._mode.init(this, iv && iv.words); + } else { + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + var finalProcessedBlocks; + + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + var wordArray; + + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + var salt; + + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt, hasher) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + if (!hasher) { + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + } else { + var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt); + } + + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + + /** + * Cipher Feedback block mode. + */ + CryptoJS.mode.CFB = (function () { + var CFB = CryptoJS.lib.BlockCipherMode.extend(); + + CFB.Encryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + CFB.Decryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + var keystream; + + // Shortcut + var iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + + return CFB; + }()); + + + /** + * Counter block mode. + */ + CryptoJS.mode.CTR = (function () { + var CTR = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = CTR.Encryptor = CTR.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTR.Decryptor = Encryptor; + + return CTR; + }()); + + + /** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ + CryptoJS.mode.CTRGladman = (function () { + var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); + + function incWord(word) + { + if (((word >> 24) & 0xff) === 0xff) { //overflow + var b1 = (word >> 16)&0xff; + var b2 = (word >> 8)&0xff; + var b3 = word & 0xff; + + if (b1 === 0xff) // overflow b1 + { + b1 = 0; + if (b2 === 0xff) + { + b2 = 0; + if (b3 === 0xff) + { + b3 = 0; + } + else + { + ++b3; + } + } + else + { + ++b2; + } + } + else + { + ++b1; + } + + word = 0; + word += (b1 << 16); + word += (b2 << 8); + word += b3; + } + else + { + word += (0x01 << 24); + } + return word; + } + + function incCounter(counter) + { + if ((counter[0] = incWord(counter[0])) === 0) + { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + counter[1] = incWord(counter[1]); + } + return counter; + } + + var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTRGladman.Decryptor = Encryptor; + + return CTRGladman; + }()); + + + + + /** + * Output Feedback block mode. + */ + CryptoJS.mode.OFB = (function () { + var OFB = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = OFB.Encryptor = OFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var keystream = this._keystream; + + // Generate keystream + if (iv) { + keystream = this._keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + OFB.Decryptor = Encryptor; + + return OFB; + }()); + + + /** + * Electronic Codebook block mode. + */ + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + } + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + } + }); + + return ECB; + }()); + + + /** + * ANSI X.923 padding strategy. + */ + CryptoJS.pad.AnsiX923 = { + pad: function (data, blockSize) { + // Shortcuts + var dataSigBytes = data.sigBytes; + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; + + // Compute last byte position + var lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + data.clamp(); + data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + data.sigBytes += nPaddingBytes; + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + /** + * ISO 10126 padding strategy. + */ + CryptoJS.pad.Iso10126 = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Pad + data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). + concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + /** + * ISO/IEC 9797-1 Padding Method 2. + */ + CryptoJS.pad.Iso97971 = { + pad: function (data, blockSize) { + // Add 0x80 byte + data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); + + // Zero pad the rest + CryptoJS.pad.ZeroPadding.pad(data, blockSize); + }, + + unpad: function (data) { + // Remove zero padding + CryptoJS.pad.ZeroPadding.unpad(data); + + // Remove one more byte -- the 0x80 byte + data.sigBytes--; + } + }; + + + /** + * Zero padding strategy. + */ + CryptoJS.pad.ZeroPadding = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Pad + data.clamp(); + data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad: function (data) { + // Shortcut + var dataWords = data.words; + + // Unpad + var i = data.sigBytes - 1; + for (var i = data.sigBytes - 1; i >= 0; i--) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + data.sigBytes = i + 1; + break; + } + } + } + }; + + + /** + * A noop padding strategy. + */ + CryptoJS.pad.NoPadding = { + pad: function () { + }, + + unpad: function () { + } + }; + + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var CipherParams = C_lib.CipherParams; + var C_enc = C.enc; + var Hex = C_enc.Hex; + var C_format = C.format; + + var HexFormatter = C_format.Hex = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify: function (cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse: function (input) { + var ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext: ciphertext }); + } + }; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + var t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6; + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Permuted Choice 1 constants + var PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4 + ]; + + // Permuted Choice 2 constants + var PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ]; + + // Cumulative bit shift constants + var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + + // SBOXes and round permutation constants + var SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002 + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000 + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100 + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040 + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080 + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008 + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001 + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800 + } + ]; + + // Masks that select the SBOX input + var SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f + ]; + + /** + * DES block cipher algorithm. + */ + var DES = C_algo.DES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Select 56 bits according to PC1 + var keyBits = []; + for (var i = 0; i < 56; i++) { + var keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1; + } + + // Assemble 16 subkeys + var subKeys = this._subKeys = []; + for (var nSubKey = 0; nSubKey < 16; nSubKey++) { + // Create subkey + var subKey = subKeys[nSubKey] = []; + + // Shortcut + var bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (var i = 0; i < 24; i++) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (var i = 1; i < 7; i++) { + subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + var invSubKeys = this._invSubKeys = []; + for (var i = 0; i < 16; i++) { + invSubKeys[i] = subKeys[15 - i]; + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + }, + + decryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + }, + + _doCryptBlock: function (M, offset, subKeys) { + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (var round = 0; round < 16; round++) { + // Shortcuts + var subKey = subKeys[round]; + var lBlock = this._lBlock; + var rBlock = this._rBlock; + + // Feistel function + var f = 0; + for (var i = 0; i < 8; i++) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + var t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + M[offset] = this._lBlock; + M[offset + 1] = this._rBlock; + }, + + keySize: 64/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + // Swap bits across the left and right words + function exchangeLR(offset, mask) { + var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; + } + + function exchangeRL(offset, mask) { + var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ + C.DES = BlockCipher._createHelper(DES); + + /** + * Triple-DES block cipher algorithm. + */ + var TripleDES = C_algo.TripleDES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + var key1 = keyWords.slice(0, 2); + var key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + var key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DES.createEncryptor(WordArray.create(key1)); + this._des2 = DES.createEncryptor(WordArray.create(key2)); + this._des3 = DES.createEncryptor(WordArray.create(key3)); + }, + + encryptBlock: function (M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + }, + + decryptBlock: function (M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + }, + + keySize: 192/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ + C.TripleDES = BlockCipher._createHelper(TripleDES); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + /** + * RC4 stream cipher algorithm. + */ + var RC4 = C_algo.RC4 = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySigBytes = key.sigBytes; + + // Init sbox + var S = this._S = []; + for (var i = 0; i < 256; i++) { + S[i] = i; + } + + // Key setup + for (var i = 0, j = 0; i < 256; i++) { + var keyByteIndex = i % keySigBytes; + var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._i = this._j = 0; + }, + + _doProcessBlock: function (M, offset) { + M[offset] ^= generateKeystreamWord.call(this); + }, + + keySize: 256/32, + + ivSize: 0 + }); + + function generateKeystreamWord() { + // Shortcuts + var S = this._S; + var i = this._i; + var j = this._j; + + // Generate keystream word + var keystreamWord = 0; + for (var n = 0; n < 4; n++) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ + C.RC4 = StreamCipher._createHelper(RC4); + + /** + * Modified RC4 stream cipher algorithm. + */ + var RC4Drop = C_algo.RC4Drop = RC4.extend({ + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + cfg: RC4.cfg.extend({ + drop: 192 + }), + + _doReset: function () { + RC4._doReset.call(this); + + // Drop + for (var i = this.cfg.drop; i > 0; i--) { + generateKeystreamWord.call(this); + } + } + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ + C.RC4Drop = StreamCipher._createHelper(RC4Drop); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm + */ + var Rabbit = C_algo.Rabbit = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Swap endian + for (var i = 0; i < 4; i++) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | + (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ + C.Rabbit = StreamCipher._createHelper(Rabbit); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ + var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ + C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + const N = 16; + + //Origin pbox and sbox, derived from PI + const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B + ]; + + const ORIG_S = [ + [ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A ], + [ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 ], + [ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 ], + [ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 ] + ]; + + var BLOWFISH_CTX = { + pbox: [], + sbox: [] + } + + function F(ctx, x){ + let a = (x >> 24) & 0xFF; + let b = (x >> 16) & 0xFF; + let c = (x >> 8) & 0xFF; + let d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; + } + + function BlowFish_Encrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; + } + + function BlowFish_Decrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; + } + + /** + * Initialization ctx's pbox and sbox. + * + * @param {Object} ctx The object has pbox and sbox. + * @param {Array} key An array of 32-bit words. + * @param {int} keysize The length of the key. + * + * @example + * + * BlowFishInit(BLOWFISH_CTX, key, 128/32); + */ + function BlowFishInit(ctx, key, keysize) + { + for(let Row = 0; Row < 4; Row++) + { + ctx.sbox[Row] = []; + for(let Col = 0; Col < 256; Col++) + { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for(let index = 0; index < N + 2; index++) + { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if(keyIndex >= keysize) + { + keyIndex = 0; + } + } + + let Data1 = 0; + let Data2 = 0; + let res = 0; + for(let i = 0; i < N + 2; i += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.pbox[i] = Data1; + ctx.pbox[i + 1] = Data2; + } + + for(let i = 0; i < 4; i++) + { + for(let j = 0; j < 256; j += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.sbox[i][j] = Data1; + ctx.sbox[i][j + 1] = Data2; + } + } + + return true; + } + + /** + * Blowfish block cipher algorithm. + */ + var Blowfish = C_algo.Blowfish = BlockCipher.extend({ + _doReset: function () { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + BlowFishInit(BLOWFISH_CTX, keyWords, keySize); + }, + + encryptBlock: function (M, offset) { + var res = BlowFish_Encrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + decryptBlock: function (M, offset) { + var res = BlowFish_Decrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + blockSize: 64/32, + + keySize: 128/32, + + ivSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ + C.Blowfish = BlockCipher._createHelper(Blowfish); + }()); + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/docs/QuickStartGuide.wiki b/node_modules/crypto-js/docs/QuickStartGuide.wiki new file mode 100644 index 0000000..2bee35d --- /dev/null +++ b/node_modules/crypto-js/docs/QuickStartGuide.wiki @@ -0,0 +1,470 @@ + + +---- + += Quick-start Guide = + +== Hashers == + +=== The Hasher Algorithms === + +==== MD5 ==== + +MD5 is a widely used hash function. It's been used in a variety of security applications and is also commonly used to check the integrity of files. Though, MD5 is not collision resistant, and it isn't suitable for applications like SSL certificates or digital signatures that rely on this property. + +{{{ + + +}}} + +==== SHA-1 ==== + +The SHA hash functions were designed by the National Security Agency (NSA). SHA-1 is the most established of the existing SHA hash functions, and it's used in a variety of security applications and protocols. Though, SHA-1's collision resistance has been weakening as new attacks are discovered or improved. + +{{{ + + +}}} + +==== SHA-2 ==== + +SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it appears to provide much better security. + +{{{ + + +}}} + +SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32. + +{{{ + + +}}} + +CryptoJS also supports SHA-224 and SHA-384, which are largely identical but truncated versions of SHA-256 and SHA-512 respectively. + +==== SHA-3 ==== + +SHA-3 is the winner of a five-year competition to select a new cryptographic hash algorithm where 64 competing designs were evaluated. + +{{{ + + +}}} + +SHA-3 can be configured to output hash lengths of one of 224, 256, 384, or 512 bits. The default is 512 bits. + +{{{ + + +}}} + +==== RIPEMD-160 ==== + +{{{ + + +}}} + +=== The Hasher Input === + +The hash algorithms accept either strings or instances of CryptoJS.lib.WordArray. A WordArray object represents an array of 32-bit words. When you pass a string, it's automatically converted to a WordArray encoded as UTF-8. + +=== The Hasher Output === + +The hash you get back isn't a string yet. It's a WordArray object. When you use a WordArray object in a string context, it's automatically converted to a hex string. + +{{{ + + +}}} + +You can convert a WordArray object to other formats by explicitly calling the toString method and passing an encoder. + +{{{ + + + +}}} + +=== Progressive Hashing === + +{{{ + + +}}} + +== HMAC == + +Keyed-hash message authentication codes (HMAC) is a mechanism for message authentication using cryptographic hash functions. + +HMAC can be used in combination with any iterated cryptographic hash function. + +{{{ + + + + + +}}} + +=== Progressive HMAC Hashing === + +{{{ + + +}}} + +== PBKDF2 == + +PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required. + +A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack. + +{{{ + + +}}} + +== Ciphers == + +=== The Cipher Algorithms === + +==== AES ==== + +The Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated. + +{{{ + + +}}} + +CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key. + +==== DES, Triple DES ==== + +DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS). DES is now considered to be insecure due to the small key size. + +{{{ + + +}}} + +Triple DES applies DES three times to each block to increase the key size. The algorithm is believed to be secure in this form. + +{{{ + + +}}} + +==== Rabbit ==== + +Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2-year process where 22 designs were evaluated. + +{{{ + + +}}} + +==== RC4, RC4Drop ==== + +RC4 is a widely-used stream cipher. It's used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security. + +{{{ + + +}}} + +It was discovered that the first few bytes of keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop. + +By default, 192 words (768 bytes) are dropped, but you can configure the algorithm to drop any number of words. + +{{{ + + +}}} + +=== Custom Key and IV === + +{{{ + + +}}} + +=== Block Modes and Padding === + +{{{ + + + + +}}} + +CryptoJS supports the following modes: + + * CBC (the default) + * CFB + * CTR + * OFB + * ECB + +And CryptoJS supports the following padding schemes: + + * Pkcs7 (the default) + * Iso97971 + * AnsiX923 + * Iso10126 + * ZeroPadding + * NoPadding + +=== The Cipher Input === + +For the plaintext message, the cipher algorithms accept either strings or instances of CryptoJS.lib.WordArray. + +For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key. If you pass the actual key, you must also pass the actual IV. + +For the ciphertext, the cipher algorithms accept either strings or instances of CryptoJS.lib.CipherParams. A CipherParams object represents a collection of parameters such as the IV, a salt, and the raw ciphertext itself. When you pass a string, it's automatically converted to a CipherParams object according to a configurable format strategy. + +=== The Cipher Output === + +The plaintext you get back after decryption is a WordArray object. See Hashers' Output for more detail. + +The ciphertext you get back after encryption isn't a string yet. It's a CipherParams object. A CipherParams object gives you access to all the parameters used during encryption. When you use a CipherParams object in a string context, it's automatically converted to a string according to a format strategy. The default is an OpenSSL-compatible format. + +{{{ + + +}}} + +You can define your own formats in order to be compatible with other crypto implementations. A format is an object with two methods—stringify and parse—that converts between CipherParams objects and ciphertext strings. + +Here's how you might write a JSON formatter: + +{{{ + + +}}} + +=== Progressive Ciphering === + +{{{ + + +}}} + +=== Interoperability === + +==== With OpenSSL ==== + +Encrypt with OpenSSL: + +{{{ +openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64 +}}} + +Decrypt with CryptoJS: + +{{{ + + +}}} + +== Encoders == + +CryptoJS can convert from encoding formats such as Base64, Latin1 or Hex to WordArray objects and vica versa. + +{{{ + + + + +}}} \ No newline at end of file diff --git a/node_modules/crypto-js/enc-base64.js b/node_modules/crypto-js/enc-base64.js new file mode 100644 index 0000000..0ffcd53 --- /dev/null +++ b/node_modules/crypto-js/enc-base64.js @@ -0,0 +1,136 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + return CryptoJS.enc.Base64; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/enc-base64url.js b/node_modules/crypto-js/enc-base64url.js new file mode 100644 index 0000000..af682e3 --- /dev/null +++ b/node_modules/crypto-js/enc-base64url.js @@ -0,0 +1,148 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64url encoding strategy. + */ + var Base64url = C_enc.Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64url.stringify(wordArray); + */ + stringify: function (wordArray, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = urlSafe ? this._safe_map : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64url.parse(base64String); + */ + parse: function (base64Str, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + + // Shortcuts + var base64StrLength = base64Str.length; + var map = urlSafe ? this._safe_map : this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + _safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + return CryptoJS.enc.Base64url; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/enc-hex.js b/node_modules/crypto-js/enc-hex.js new file mode 100644 index 0000000..88161ff --- /dev/null +++ b/node_modules/crypto-js/enc-hex.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Hex; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/enc-latin1.js b/node_modules/crypto-js/enc-latin1.js new file mode 100644 index 0000000..ade56dc --- /dev/null +++ b/node_modules/crypto-js/enc-latin1.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Latin1; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/enc-utf16.js b/node_modules/crypto-js/enc-utf16.js new file mode 100644 index 0000000..7de6245 --- /dev/null +++ b/node_modules/crypto-js/enc-utf16.js @@ -0,0 +1,149 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * UTF-16 BE encoding strategy. + */ + var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + /** + * UTF-16 LE encoding strategy. + */ + C_enc.Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + function swapEndian(word) { + return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + } + }()); + + + return CryptoJS.enc.Utf16; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/enc-utf8.js b/node_modules/crypto-js/enc-utf8.js new file mode 100644 index 0000000..e7a251d --- /dev/null +++ b/node_modules/crypto-js/enc-utf8.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Utf8; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/evpkdf.js b/node_modules/crypto-js/evpkdf.js new file mode 100644 index 0000000..578974a --- /dev/null +++ b/node_modules/crypto-js/evpkdf.js @@ -0,0 +1,134 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + var block; + + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.EvpKDF; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/format-hex.js b/node_modules/crypto-js/format-hex.js new file mode 100644 index 0000000..2e9a861 --- /dev/null +++ b/node_modules/crypto-js/format-hex.js @@ -0,0 +1,66 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var CipherParams = C_lib.CipherParams; + var C_enc = C.enc; + var Hex = C_enc.Hex; + var C_format = C.format; + + var HexFormatter = C_format.Hex = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify: function (cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse: function (input) { + var ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext: ciphertext }); + } + }; + }()); + + + return CryptoJS.format.Hex; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/format-openssl.js b/node_modules/crypto-js/format-openssl.js new file mode 100644 index 0000000..3373edc --- /dev/null +++ b/node_modules/crypto-js/format-openssl.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.format.OpenSSL; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-md5.js b/node_modules/crypto-js/hmac-md5.js new file mode 100644 index 0000000..ad7a90a --- /dev/null +++ b/node_modules/crypto-js/hmac-md5.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./md5", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacMD5; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-ripemd160.js b/node_modules/crypto-js/hmac-ripemd160.js new file mode 100644 index 0000000..73d55a7 --- /dev/null +++ b/node_modules/crypto-js/hmac-ripemd160.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./ripemd160", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacRIPEMD160; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha1.js b/node_modules/crypto-js/hmac-sha1.js new file mode 100644 index 0000000..0b570cb --- /dev/null +++ b/node_modules/crypto-js/hmac-sha1.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA1; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha224.js b/node_modules/crypto-js/hmac-sha224.js new file mode 100644 index 0000000..3778863 --- /dev/null +++ b/node_modules/crypto-js/hmac-sha224.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./sha224", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA224; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha256.js b/node_modules/crypto-js/hmac-sha256.js new file mode 100644 index 0000000..33b0c9f --- /dev/null +++ b/node_modules/crypto-js/hmac-sha256.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA256; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha3.js b/node_modules/crypto-js/hmac-sha3.js new file mode 100644 index 0000000..1248804 --- /dev/null +++ b/node_modules/crypto-js/hmac-sha3.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha3"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha3", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA3; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha384.js b/node_modules/crypto-js/hmac-sha384.js new file mode 100644 index 0000000..0036e2b --- /dev/null +++ b/node_modules/crypto-js/hmac-sha384.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./sha384"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512", "./sha384", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA384; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac-sha512.js b/node_modules/crypto-js/hmac-sha512.js new file mode 100644 index 0000000..c1005b6 --- /dev/null +++ b/node_modules/crypto-js/hmac-sha512.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA512; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/hmac.js b/node_modules/crypto-js/hmac.js new file mode 100644 index 0000000..8c09851 --- /dev/null +++ b/node_modules/crypto-js/hmac.js @@ -0,0 +1,143 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/index.js b/node_modules/crypto-js/index.js new file mode 100644 index 0000000..b696646 --- /dev/null +++ b/node_modules/crypto-js/index.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./lib-typedarrays"), require("./enc-utf16"), require("./enc-base64"), require("./enc-base64url"), require("./md5"), require("./sha1"), require("./sha256"), require("./sha224"), require("./sha512"), require("./sha384"), require("./sha3"), require("./ripemd160"), require("./hmac"), require("./pbkdf2"), require("./evpkdf"), require("./cipher-core"), require("./mode-cfb"), require("./mode-ctr"), require("./mode-ctr-gladman"), require("./mode-ofb"), require("./mode-ecb"), require("./pad-ansix923"), require("./pad-iso10126"), require("./pad-iso97971"), require("./pad-zeropadding"), require("./pad-nopadding"), require("./format-hex"), require("./aes"), require("./tripledes"), require("./rc4"), require("./rabbit"), require("./rabbit-legacy"), require("./blowfish")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./lib-typedarrays", "./enc-utf16", "./enc-base64", "./enc-base64url", "./md5", "./sha1", "./sha256", "./sha224", "./sha512", "./sha384", "./sha3", "./ripemd160", "./hmac", "./pbkdf2", "./evpkdf", "./cipher-core", "./mode-cfb", "./mode-ctr", "./mode-ctr-gladman", "./mode-ofb", "./mode-ecb", "./pad-ansix923", "./pad-iso10126", "./pad-iso97971", "./pad-zeropadding", "./pad-nopadding", "./format-hex", "./aes", "./tripledes", "./rc4", "./rabbit", "./rabbit-legacy", "./blowfish"], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/lib-typedarrays.js b/node_modules/crypto-js/lib-typedarrays.js new file mode 100644 index 0000000..264b210 --- /dev/null +++ b/node_modules/crypto-js/lib-typedarrays.js @@ -0,0 +1,76 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; + }()); + + + return CryptoJS.lib.WordArray; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/md5.js b/node_modules/crypto-js/md5.js new file mode 100644 index 0000000..72fce03 --- /dev/null +++ b/node_modules/crypto-js/md5.js @@ -0,0 +1,268 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + return CryptoJS.MD5; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/mode-cfb.js b/node_modules/crypto-js/mode-cfb.js new file mode 100644 index 0000000..444c9cb --- /dev/null +++ b/node_modules/crypto-js/mode-cfb.js @@ -0,0 +1,80 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher Feedback block mode. + */ + CryptoJS.mode.CFB = (function () { + var CFB = CryptoJS.lib.BlockCipherMode.extend(); + + CFB.Encryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + CFB.Decryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + var keystream; + + // Shortcut + var iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + + return CFB; + }()); + + + return CryptoJS.mode.CFB; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/mode-ctr-gladman.js b/node_modules/crypto-js/mode-ctr-gladman.js new file mode 100644 index 0000000..bbc5687 --- /dev/null +++ b/node_modules/crypto-js/mode-ctr-gladman.js @@ -0,0 +1,116 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ + CryptoJS.mode.CTRGladman = (function () { + var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); + + function incWord(word) + { + if (((word >> 24) & 0xff) === 0xff) { //overflow + var b1 = (word >> 16)&0xff; + var b2 = (word >> 8)&0xff; + var b3 = word & 0xff; + + if (b1 === 0xff) // overflow b1 + { + b1 = 0; + if (b2 === 0xff) + { + b2 = 0; + if (b3 === 0xff) + { + b3 = 0; + } + else + { + ++b3; + } + } + else + { + ++b2; + } + } + else + { + ++b1; + } + + word = 0; + word += (b1 << 16); + word += (b2 << 8); + word += b3; + } + else + { + word += (0x01 << 24); + } + return word; + } + + function incCounter(counter) + { + if ((counter[0] = incWord(counter[0])) === 0) + { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + counter[1] = incWord(counter[1]); + } + return counter; + } + + var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTRGladman.Decryptor = Encryptor; + + return CTRGladman; + }()); + + + + + return CryptoJS.mode.CTRGladman; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/mode-ctr.js b/node_modules/crypto-js/mode-ctr.js new file mode 100644 index 0000000..c3d470a --- /dev/null +++ b/node_modules/crypto-js/mode-ctr.js @@ -0,0 +1,58 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Counter block mode. + */ + CryptoJS.mode.CTR = (function () { + var CTR = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = CTR.Encryptor = CTR.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTR.Decryptor = Encryptor; + + return CTR; + }()); + + + return CryptoJS.mode.CTR; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/mode-ecb.js b/node_modules/crypto-js/mode-ecb.js new file mode 100644 index 0000000..ff06921 --- /dev/null +++ b/node_modules/crypto-js/mode-ecb.js @@ -0,0 +1,40 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Electronic Codebook block mode. + */ + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + } + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + } + }); + + return ECB; + }()); + + + return CryptoJS.mode.ECB; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/mode-ofb.js b/node_modules/crypto-js/mode-ofb.js new file mode 100644 index 0000000..c01314c --- /dev/null +++ b/node_modules/crypto-js/mode-ofb.js @@ -0,0 +1,54 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Output Feedback block mode. + */ + CryptoJS.mode.OFB = (function () { + var OFB = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = OFB.Encryptor = OFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var keystream = this._keystream; + + // Generate keystream + if (iv) { + keystream = this._keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + OFB.Decryptor = Encryptor; + + return OFB; + }()); + + + return CryptoJS.mode.OFB; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/package.json b/node_modules/crypto-js/package.json new file mode 100644 index 0000000..4b9a8e2 --- /dev/null +++ b/node_modules/crypto-js/package.json @@ -0,0 +1,42 @@ +{ + "name": "crypto-js", + "version": "4.2.0", + "description": "JavaScript library of crypto standards.", + "license": "MIT", + "author": { + "name": "Evan Vosberg", + "url": "http://github.com/evanvosberg" + }, + "homepage": "http://github.com/brix/crypto-js", + "repository": { + "type": "git", + "url": "http://github.com/brix/crypto-js.git" + }, + "keywords": [ + "security", + "crypto", + "Hash", + "MD5", + "SHA1", + "SHA-1", + "SHA256", + "SHA-256", + "RC4", + "Rabbit", + "AES", + "DES", + "PBKDF2", + "HMAC", + "OFB", + "CFB", + "CTR", + "CBC", + "Base64", + "Base64url" + ], + "main": "index.js", + "dependencies": {}, + "browser": { + "crypto": false + } +} diff --git a/node_modules/crypto-js/pad-ansix923.js b/node_modules/crypto-js/pad-ansix923.js new file mode 100644 index 0000000..f01f21e --- /dev/null +++ b/node_modules/crypto-js/pad-ansix923.js @@ -0,0 +1,49 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ANSI X.923 padding strategy. + */ + CryptoJS.pad.AnsiX923 = { + pad: function (data, blockSize) { + // Shortcuts + var dataSigBytes = data.sigBytes; + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; + + // Compute last byte position + var lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + data.clamp(); + data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + data.sigBytes += nPaddingBytes; + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Ansix923; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pad-iso10126.js b/node_modules/crypto-js/pad-iso10126.js new file mode 100644 index 0000000..6e2aefd --- /dev/null +++ b/node_modules/crypto-js/pad-iso10126.js @@ -0,0 +1,44 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO 10126 padding strategy. + */ + CryptoJS.pad.Iso10126 = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Pad + data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). + concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Iso10126; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pad-iso97971.js b/node_modules/crypto-js/pad-iso97971.js new file mode 100644 index 0000000..41049b4 --- /dev/null +++ b/node_modules/crypto-js/pad-iso97971.js @@ -0,0 +1,40 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO/IEC 9797-1 Padding Method 2. + */ + CryptoJS.pad.Iso97971 = { + pad: function (data, blockSize) { + // Add 0x80 byte + data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); + + // Zero pad the rest + CryptoJS.pad.ZeroPadding.pad(data, blockSize); + }, + + unpad: function (data) { + // Remove zero padding + CryptoJS.pad.ZeroPadding.unpad(data); + + // Remove one more byte -- the 0x80 byte + data.sigBytes--; + } + }; + + + return CryptoJS.pad.Iso97971; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pad-nopadding.js b/node_modules/crypto-js/pad-nopadding.js new file mode 100644 index 0000000..c7787c9 --- /dev/null +++ b/node_modules/crypto-js/pad-nopadding.js @@ -0,0 +1,30 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * A noop padding strategy. + */ + CryptoJS.pad.NoPadding = { + pad: function () { + }, + + unpad: function () { + } + }; + + + return CryptoJS.pad.NoPadding; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pad-pkcs7.js b/node_modules/crypto-js/pad-pkcs7.js new file mode 100644 index 0000000..3555168 --- /dev/null +++ b/node_modules/crypto-js/pad-pkcs7.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.pad.Pkcs7; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pad-zeropadding.js b/node_modules/crypto-js/pad-zeropadding.js new file mode 100644 index 0000000..a1a459e --- /dev/null +++ b/node_modules/crypto-js/pad-zeropadding.js @@ -0,0 +1,47 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Zero padding strategy. + */ + CryptoJS.pad.ZeroPadding = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Pad + data.clamp(); + data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad: function (data) { + // Shortcut + var dataWords = data.words; + + // Unpad + var i = data.sigBytes - 1; + for (var i = data.sigBytes - 1; i >= 0; i--) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + data.sigBytes = i + 1; + break; + } + } + } + }; + + + return CryptoJS.pad.ZeroPadding; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/pbkdf2.js b/node_modules/crypto-js/pbkdf2.js new file mode 100644 index 0000000..6850934 --- /dev/null +++ b/node_modules/crypto-js/pbkdf2.js @@ -0,0 +1,145 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + var HMAC = C_algo.HMAC; + + /** + * Password-Based Key Derivation Function 2 algorithm. + */ + var PBKDF2 = C_algo.PBKDF2 = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: SHA256, + iterations: 250000 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.PBKDF2.create(); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init HMAC + var hmac = HMAC.create(cfg.hasher, password); + + // Initial values + var derivedKey = WordArray.create(); + var blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var blockIndexWords = blockIndex.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + var block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + var blockWords = block.words; + var blockWordsLength = blockWords.length; + + // Iterations + var intermediate = block; + for (var i = 1; i < iterations; i++) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + var intermediateWords = intermediate.words; + + // XOR intermediate with block + for (var j = 0; j < blockWordsLength; j++) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0]++; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.PBKDF2 = function (password, salt, cfg) { + return PBKDF2.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.PBKDF2; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/rabbit-legacy.js b/node_modules/crypto-js/rabbit-legacy.js new file mode 100644 index 0000000..e118b6b --- /dev/null +++ b/node_modules/crypto-js/rabbit-legacy.js @@ -0,0 +1,190 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ + var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ + C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); + }()); + + + return CryptoJS.RabbitLegacy; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/rabbit.js b/node_modules/crypto-js/rabbit.js new file mode 100644 index 0000000..1b06833 --- /dev/null +++ b/node_modules/crypto-js/rabbit.js @@ -0,0 +1,192 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm + */ + var Rabbit = C_algo.Rabbit = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Swap endian + for (var i = 0; i < 4; i++) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | + (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ + C.Rabbit = StreamCipher._createHelper(Rabbit); + }()); + + + return CryptoJS.Rabbit; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/rc4.js b/node_modules/crypto-js/rc4.js new file mode 100644 index 0000000..0e4bdff --- /dev/null +++ b/node_modules/crypto-js/rc4.js @@ -0,0 +1,139 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + /** + * RC4 stream cipher algorithm. + */ + var RC4 = C_algo.RC4 = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySigBytes = key.sigBytes; + + // Init sbox + var S = this._S = []; + for (var i = 0; i < 256; i++) { + S[i] = i; + } + + // Key setup + for (var i = 0, j = 0; i < 256; i++) { + var keyByteIndex = i % keySigBytes; + var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._i = this._j = 0; + }, + + _doProcessBlock: function (M, offset) { + M[offset] ^= generateKeystreamWord.call(this); + }, + + keySize: 256/32, + + ivSize: 0 + }); + + function generateKeystreamWord() { + // Shortcuts + var S = this._S; + var i = this._i; + var j = this._j; + + // Generate keystream word + var keystreamWord = 0; + for (var n = 0; n < 4; n++) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ + C.RC4 = StreamCipher._createHelper(RC4); + + /** + * Modified RC4 stream cipher algorithm. + */ + var RC4Drop = C_algo.RC4Drop = RC4.extend({ + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + cfg: RC4.cfg.extend({ + drop: 192 + }), + + _doReset: function () { + RC4._doReset.call(this); + + // Drop + for (var i = this.cfg.drop; i > 0; i--) { + generateKeystreamWord.call(this); + } + } + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ + C.RC4Drop = StreamCipher._createHelper(RC4Drop); + }()); + + + return CryptoJS.RC4; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/ripemd160.js b/node_modules/crypto-js/ripemd160.js new file mode 100644 index 0000000..24feb47 --- /dev/null +++ b/node_modules/crypto-js/ripemd160.js @@ -0,0 +1,267 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + (c) 2012 by Cédric Mesnil. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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. + */ + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); + var _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); + var _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); + var _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); + + var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); + var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + + /** + * RIPEMD160 hash algorithm. + */ + var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ + _doReset: function () { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + }, + + _doProcessBlock: function (M, offset) { + + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + // Swap + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + var H = this._hash.words; + var hl = _hl.words; + var hr = _hr.words; + var zl = _zl.words; + var zr = _zr.words; + var sl = _sl.words; + var sr = _sr.words; + + // Working variables + var al, bl, cl, dl, el; + var ar, br, cr, dr, er; + + ar = al = H[0]; + br = bl = H[1]; + cr = cl = H[2]; + dr = dl = H[3]; + er = el = H[4]; + // Computation + var t; + for (var i = 0; i < 80; i += 1) { + t = (al + M[offset+zl[i]])|0; + if (i<16){ + t += f1(bl,cl,dl) + hl[0]; + } else if (i<32) { + t += f2(bl,cl,dl) + hl[1]; + } else if (i<48) { + t += f3(bl,cl,dl) + hl[2]; + } else if (i<64) { + t += f4(bl,cl,dl) + hl[3]; + } else {// if (i<80) { + t += f5(bl,cl,dl) + hl[4]; + } + t = t|0; + t = rotl(t,sl[i]); + t = (t+el)|0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + M[offset+zr[i]])|0; + if (i<16){ + t += f5(br,cr,dr) + hr[0]; + } else if (i<32) { + t += f4(br,cr,dr) + hr[1]; + } else if (i<48) { + t += f3(br,cr,dr) + hr[2]; + } else if (i<64) { + t += f2(br,cr,dr) + hr[3]; + } else {// if (i<80) { + t += f1(br,cr,dr) + hr[4]; + } + t = t|0; + t = rotl(t,sr[i]) ; + t = (t+er)|0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr)|0; + H[1] = (H[2] + dl + er)|0; + H[2] = (H[3] + el + ar)|0; + H[3] = (H[4] + al + br)|0; + H[4] = (H[0] + bl + cr)|0; + H[0] = t; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | + (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 5; i++) { + // Shortcut + var H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + + function f1(x, y, z) { + return ((x) ^ (y) ^ (z)); + + } + + function f2(x, y, z) { + return (((x)&(y)) | ((~x)&(z))); + } + + function f3(x, y, z) { + return (((x) | (~(y))) ^ (z)); + } + + function f4(x, y, z) { + return (((x) & (z)) | ((y)&(~(z)))); + } + + function f5(x, y, z) { + return ((x) ^ ((y) |(~(z)))); + + } + + function rotl(x,n) { + return (x<>>(32-n)); + } + + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ + C.RIPEMD160 = Hasher._createHelper(RIPEMD160); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ + C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); + }(Math)); + + + return CryptoJS.RIPEMD160; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha1.js b/node_modules/crypto-js/sha1.js new file mode 100644 index 0000000..6691149 --- /dev/null +++ b/node_modules/crypto-js/sha1.js @@ -0,0 +1,150 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + return CryptoJS.SHA1; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha224.js b/node_modules/crypto-js/sha224.js new file mode 100644 index 0000000..d8ce988 --- /dev/null +++ b/node_modules/crypto-js/sha224.js @@ -0,0 +1,80 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + + /** + * SHA-224 hash algorithm. + */ + var SHA224 = C_algo.SHA224 = SHA256.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]); + }, + + _doFinalize: function () { + var hash = SHA256._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ + C.SHA224 = SHA256._createHelper(SHA224); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ + C.HmacSHA224 = SHA256._createHmacHelper(SHA224); + }()); + + + return CryptoJS.SHA224; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha256.js b/node_modules/crypto-js/sha256.js new file mode 100644 index 0000000..de2d7fc --- /dev/null +++ b/node_modules/crypto-js/sha256.js @@ -0,0 +1,199 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + }(Math)); + + + return CryptoJS.SHA256; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha3.js b/node_modules/crypto-js/sha3.js new file mode 100644 index 0000000..34ad86c --- /dev/null +++ b/node_modules/crypto-js/sha3.js @@ -0,0 +1,326 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var C_algo = C.algo; + + // Constants tables + var RHO_OFFSETS = []; + var PI_INDEXES = []; + var ROUND_CONSTANTS = []; + + // Compute Constants + (function () { + // Compute rho offset constants + var x = 1, y = 0; + for (var t = 0; t < 24; t++) { + RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; + + var newX = y % 5; + var newY = (2 * x + 3 * y) % 5; + x = newX; + y = newY; + } + + // Compute pi index constants + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } + } + + // Compute round constants + var LFSR = 0x01; + for (var i = 0; i < 24; i++) { + var roundConstantMsw = 0; + var roundConstantLsw = 0; + + for (var j = 0; j < 7; j++) { + if (LFSR & 0x01) { + var bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); + } + }()); + + // Reusable objects for temporary values + var T = []; + (function () { + for (var i = 0; i < 25; i++) { + T[i] = X64Word.create(); + } + }()); + + /** + * SHA-3 hash algorithm. + */ + var SHA3 = C_algo.SHA3 = Hasher.extend({ + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + cfg: Hasher.cfg.extend({ + outputLength: 512 + }), + + _doReset: function () { + var state = this._state = [] + for (var i = 0; i < 25; i++) { + state[i] = new X64Word.init(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var state = this._state; + var nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (var i = 0; i < nBlockSizeLanes; i++) { + // Shortcuts + var M2i = M[offset + 2 * i]; + var M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = ( + (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | + (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) + ); + M2i1 = ( + (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | + (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) + ); + + // Absorb message into state + var lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (var round = 0; round < 24; round++) { + // Theta + for (var x = 0; x < 5; x++) { + // Mix column lanes + var tMsw = 0, tLsw = 0; + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + var Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (var x = 0; x < 5; x++) { + // Shortcuts + var Tx4 = T[(x + 4) % 5]; + var Tx1 = T[(x + 1) % 5]; + var Tx1Msw = Tx1.high; + var Tx1Lsw = Tx1.low; + + // Mix surrounding columns + var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (var laneIndex = 1; laneIndex < 25; laneIndex++) { + var tMsw; + var tLsw; + + // Shortcuts + var lane = state[laneIndex]; + var laneMsw = lane.high; + var laneLsw = lane.low; + var rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + var TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + var T0 = T[0]; + var state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + // Shortcuts + var laneIndex = x + 5 * y; + var lane = state[laneIndex]; + var TLane = T[laneIndex]; + var Tx1Lane = T[((x + 1) % 5) + 5 * y]; + var Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + var lane = state[0]; + var roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + var blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var state = this._state; + var outputLengthBytes = this.cfg.outputLength / 8; + var outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + var hashWords = []; + for (var i = 0; i < outputLengthLanes; i++) { + // Shortcuts + var lane = state[i]; + var laneMsw = lane.high; + var laneLsw = lane.low; + + // Swap endian + laneMsw = ( + (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | + (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) + ); + laneLsw = ( + (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | + (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) + ); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray.init(hashWords, outputLengthBytes); + }, + + clone: function () { + var clone = Hasher.clone.call(this); + + var state = clone._state = this._state.slice(0); + for (var i = 0; i < 25; i++) { + state[i] = state[i].clone(); + } + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ + C.SHA3 = Hasher._createHelper(SHA3); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ + C.HmacSHA3 = Hasher._createHmacHelper(SHA3); + }(Math)); + + + return CryptoJS.SHA3; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha384.js b/node_modules/crypto-js/sha384.js new file mode 100644 index 0000000..a0b95bf --- /dev/null +++ b/node_modules/crypto-js/sha384.js @@ -0,0 +1,83 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + var SHA512 = C_algo.SHA512; + + /** + * SHA-384 hash algorithm. + */ + var SHA384 = C_algo.SHA384 = SHA512.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), + new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), + new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), + new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) + ]); + }, + + _doFinalize: function () { + var hash = SHA512._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ + C.SHA384 = SHA512._createHelper(SHA384); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ + C.HmacSHA384 = SHA512._createHmacHelper(SHA384); + }()); + + + return CryptoJS.SHA384; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/sha512.js b/node_modules/crypto-js/sha512.js new file mode 100644 index 0000000..d274ab0 --- /dev/null +++ b/node_modules/crypto-js/sha512.js @@ -0,0 +1,326 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + + function X64Word_create() { + return X64Word.create.apply(X64Word, arguments); + } + + // Constants + var K = [ + X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), + X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), + X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), + X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), + X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), + X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), + X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), + X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), + X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), + X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), + X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), + X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), + X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), + X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), + X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), + X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), + X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), + X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), + X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), + X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), + X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), + X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), + X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), + X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), + X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), + X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), + X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), + X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), + X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), + X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), + X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), + X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), + X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), + X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), + X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), + X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), + X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), + X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), + X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), + X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) + ]; + + // Reusable objects + var W = []; + (function () { + for (var i = 0; i < 80; i++) { + W[i] = X64Word_create(); + } + }()); + + /** + * SHA-512 hash algorithm. + */ + var SHA512 = C_algo.SHA512 = Hasher.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), + new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), + new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), + new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var H = this._hash.words; + + var H0 = H[0]; + var H1 = H[1]; + var H2 = H[2]; + var H3 = H[3]; + var H4 = H[4]; + var H5 = H[5]; + var H6 = H[6]; + var H7 = H[7]; + + var H0h = H0.high; + var H0l = H0.low; + var H1h = H1.high; + var H1l = H1.low; + var H2h = H2.high; + var H2l = H2.low; + var H3h = H3.high; + var H3l = H3.low; + var H4h = H4.high; + var H4l = H4.low; + var H5h = H5.high; + var H5l = H5.low; + var H6h = H6.high; + var H6l = H6.low; + var H7h = H7.high; + var H7l = H7.low; + + // Working variables + var ah = H0h; + var al = H0l; + var bh = H1h; + var bl = H1l; + var ch = H2h; + var cl = H2l; + var dh = H3h; + var dl = H3l; + var eh = H4h; + var el = H4l; + var fh = H5h; + var fl = H5l; + var gh = H6h; + var gl = H6l; + var hh = H7h; + var hl = H7l; + + // Rounds + for (var i = 0; i < 80; i++) { + var Wil; + var Wih; + + // Shortcut + var Wi = W[i]; + + // Extend message + if (i < 16) { + Wih = Wi.high = M[offset + i * 2] | 0; + Wil = Wi.low = M[offset + i * 2 + 1] | 0; + } else { + // Gamma0 + var gamma0x = W[i - 15]; + var gamma0xh = gamma0x.high; + var gamma0xl = gamma0x.low; + var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); + var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + var gamma1x = W[i - 2]; + var gamma1xh = gamma1x.high; + var gamma1xl = gamma1x.low; + var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); + var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7 = W[i - 7]; + var Wi7h = Wi7.high; + var Wi7l = Wi7.low; + + var Wi16 = W[i - 16]; + var Wi16h = Wi16.high; + var Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil = Wil + gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil = Wil + Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + var chh = (eh & fh) ^ (~eh & gh); + var chl = (el & fl) ^ (~el & gl); + var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + var majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); + var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); + var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); + var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + var Ki = K[i]; + var Kih = Ki.high; + var Kil = Ki.low; + + var t1l = hl + sigma1l; + var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + var t1l = t1l + chl; + var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + var t1l = t1l + Kil; + var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + var t1l = t1l + Wil; + var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + var t2l = sigma0l + majl; + var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0l = H0.low = (H0l + al); + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1l = H1.low = (H1l + bl); + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2l = H2.low = (H2l + cl); + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3l = H3.low = (H3l + dl); + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4l = H4.low = (H4l + el); + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5l = H5.low = (H5l + fl); + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6l = H6.low = (H6l + gl); + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7l = H7.low = (H7l + hl); + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + var hash = this._hash.toX32(); + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + }, + + blockSize: 1024/32 + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ + C.SHA512 = Hasher._createHelper(SHA512); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ + C.HmacSHA512 = Hasher._createHmacHelper(SHA512); + }()); + + + return CryptoJS.SHA512; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/tripledes.js b/node_modules/crypto-js/tripledes.js new file mode 100644 index 0000000..1a92477 --- /dev/null +++ b/node_modules/crypto-js/tripledes.js @@ -0,0 +1,779 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Permuted Choice 1 constants + var PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4 + ]; + + // Permuted Choice 2 constants + var PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ]; + + // Cumulative bit shift constants + var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + + // SBOXes and round permutation constants + var SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002 + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000 + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100 + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040 + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080 + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008 + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001 + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800 + } + ]; + + // Masks that select the SBOX input + var SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f + ]; + + /** + * DES block cipher algorithm. + */ + var DES = C_algo.DES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Select 56 bits according to PC1 + var keyBits = []; + for (var i = 0; i < 56; i++) { + var keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1; + } + + // Assemble 16 subkeys + var subKeys = this._subKeys = []; + for (var nSubKey = 0; nSubKey < 16; nSubKey++) { + // Create subkey + var subKey = subKeys[nSubKey] = []; + + // Shortcut + var bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (var i = 0; i < 24; i++) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (var i = 1; i < 7; i++) { + subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + var invSubKeys = this._invSubKeys = []; + for (var i = 0; i < 16; i++) { + invSubKeys[i] = subKeys[15 - i]; + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + }, + + decryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + }, + + _doCryptBlock: function (M, offset, subKeys) { + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (var round = 0; round < 16; round++) { + // Shortcuts + var subKey = subKeys[round]; + var lBlock = this._lBlock; + var rBlock = this._rBlock; + + // Feistel function + var f = 0; + for (var i = 0; i < 8; i++) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + var t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + M[offset] = this._lBlock; + M[offset + 1] = this._rBlock; + }, + + keySize: 64/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + // Swap bits across the left and right words + function exchangeLR(offset, mask) { + var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; + } + + function exchangeRL(offset, mask) { + var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ + C.DES = BlockCipher._createHelper(DES); + + /** + * Triple-DES block cipher algorithm. + */ + var TripleDES = C_algo.TripleDES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + var key1 = keyWords.slice(0, 2); + var key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + var key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DES.createEncryptor(WordArray.create(key1)); + this._des2 = DES.createEncryptor(WordArray.create(key2)); + this._des3 = DES.createEncryptor(WordArray.create(key3)); + }, + + encryptBlock: function (M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + }, + + decryptBlock: function (M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + }, + + keySize: 192/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ + C.TripleDES = BlockCipher._createHelper(TripleDES); + }()); + + + return CryptoJS.TripleDES; + +})); \ No newline at end of file diff --git a/node_modules/crypto-js/x64-core.js b/node_modules/crypto-js/x64-core.js new file mode 100644 index 0000000..57dcc14 --- /dev/null +++ b/node_modules/crypto-js/x64-core.js @@ -0,0 +1,304 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var X32WordArray = C_lib.WordArray; + + /** + * x64 namespace. + */ + var C_x64 = C.x64 = {}; + + /** + * A 64-bit word. + */ + var X64Word = C_x64.Word = Base.extend({ + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + init: function (high, low) { + this.high = high; + this.low = low; + } + + /** + * Bitwise NOTs this word. + * + * @return {X64Word} A new x64-Word object after negating. + * + * @example + * + * var negated = x64Word.not(); + */ + // not: function () { + // var high = ~this.high; + // var low = ~this.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ANDs this word with the passed word. + * + * @param {X64Word} word The x64-Word to AND with this word. + * + * @return {X64Word} A new x64-Word object after ANDing. + * + * @example + * + * var anded = x64Word.and(anotherX64Word); + */ + // and: function (word) { + // var high = this.high & word.high; + // var low = this.low & word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to OR with this word. + * + * @return {X64Word} A new x64-Word object after ORing. + * + * @example + * + * var ored = x64Word.or(anotherX64Word); + */ + // or: function (word) { + // var high = this.high | word.high; + // var low = this.low | word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise XORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to XOR with this word. + * + * @return {X64Word} A new x64-Word object after XORing. + * + * @example + * + * var xored = x64Word.xor(anotherX64Word); + */ + // xor: function (word) { + // var high = this.high ^ word.high; + // var low = this.low ^ word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the left. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftL(25); + */ + // shiftL: function (n) { + // if (n < 32) { + // var high = (this.high << n) | (this.low >>> (32 - n)); + // var low = this.low << n; + // } else { + // var high = this.low << (n - 32); + // var low = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the right. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftR(7); + */ + // shiftR: function (n) { + // if (n < 32) { + // var low = (this.low >>> n) | (this.high << (32 - n)); + // var high = this.high >>> n; + // } else { + // var low = this.high >>> (n - 32); + // var high = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Rotates this word n bits to the left. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotL(25); + */ + // rotL: function (n) { + // return this.shiftL(n).or(this.shiftR(64 - n)); + // }, + + /** + * Rotates this word n bits to the right. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotR(7); + */ + // rotR: function (n) { + // return this.shiftR(n).or(this.shiftL(64 - n)); + // }, + + /** + * Adds this word with the passed word. + * + * @param {X64Word} word The x64-Word to add with this word. + * + * @return {X64Word} A new x64-Word object after adding. + * + * @example + * + * var added = x64Word.add(anotherX64Word); + */ + // add: function (word) { + // var low = (this.low + word.low) | 0; + // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; + // var high = (this.high + word.high + carry) | 0; + + // return X64Word.create(high, low); + // } + }); + + /** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var X64WordArray = C_x64.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 8; + } + }, + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32: function () { + // Shortcuts + var x64Words = this.words; + var x64WordsLength = x64Words.length; + + // Convert + var x32Words = []; + for (var i = 0; i < x64WordsLength; i++) { + var x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + }, + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + + // Clone "words" array + var words = clone.words = this.words.slice(0); + + // Clone each X64Word object + var wordsLength = words.length; + for (var i = 0; i < wordsLength; i++) { + words[i] = words[i].clone(); + } + + return clone; + } + }); + }()); + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c168ff3 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,17 @@ +{ + "name": "SanYeCao-Nonebot", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "crypto-js": "^4.2.0" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9bd309c --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "crypto-js": "^4.2.0" + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..982f3e7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +[project] +name = "SanYeCao-Nonebot" +version = "0.1.0" +description = "SanYeCao-Nonebot" +readme = "README.md" +requires-python = ">=3.9, <4.0" + +[tool.nonebot] +adapters = [ + { name = "QQ", module_name = "nonebot.adapters.qq" } +] +plugins = [] +plugin_dirs = ["src/plugins"] +builtin_plugins = ["echo"] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..574768e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,37 @@ +nonebot2 +nonebot_adapter_qq +nonebot2[fastapi] +nonebot2[httpx] +nonebot2[websockets] + +ffmpeg-python +sqlalchemy +selenium +autopep8 +graiax-silkcoder[ffmpeg] +Crypto +graiax-silkcoder +Crypto +fake_useragent +pycryptodome +PyExecJS +gradio_client +tortoise-orm +urllib3 +zhdate +chinese_calendar +lunardate +playwright +nonebot-plugin-htmlrender +tenacity +paramiko + +requests +pillow +pyyaml +qrcode +lazy_object_proxy +openai +typing_extensions +psutil +Beautifulsoup4 \ No newline at end of file diff --git a/src/clover_image/add_text_to_image.py b/src/clover_image/add_text_to_image.py new file mode 100644 index 0000000..17fc053 --- /dev/null +++ b/src/clover_image/add_text_to_image.py @@ -0,0 +1,72 @@ +from PIL import Image, ImageDraw,ImageFont + + +""" +图文合成 +""" +async def add_text_to_image(image_path, output_path,content,font_path, font_size, text_color,text_position ,position): + """ + 给图片添加文字 + :param image_path: 输入图片的路径 + :param output_path: 合成后的图片名称 + :param content: 要添加的文字内容 + :param font_path: 字体文件路径 + :param font_size: 文字的字体大小 + :param text_color: 文字颜色 (255, 0, 0) "#FF0000" "red" + :param text_position: 文字对齐方式,可选值:"left", "center", "right" + :param position: 文字位置,可选值:"left", "right", "center", "top", "bottom", "top left corner", "top right corner", "bottom left corner", "bottom right corner" + :return: + """ + # 打开图片 + image = Image.open(image_path) + # 创建一个可用于绘制的对象 + draw = ImageDraw.Draw(image) + # 设置字体和字体大小 + font = ImageFont.truetype(font_path, font_size) + + wrapped_text,current_width = "",0 + + # 遍历文本中的每个字符 + for char in content: + # 获取字符的宽度 + char_width, _ = draw.textbbox((0, 0), char, font=font)[2:] + # 如果当前行的宽度加上字符宽度超过图片指定宽度,则换行 + if current_width + char_width > image.width * 9 // 10: # 这里是图片的十分之九 + wrapped_text += "\n" + current_width = 0 + # 将字符添加到当前行 + wrapped_text += char + # 更新当前行的宽度 + current_width += char_width + + # 获取换行后文本的宽度和高度 + text_width, text_height = draw.textbbox((0, 0), wrapped_text, font=font)[2:] + + # 根据位置参数计算文本的位置 + if position == "left": + position = (0, (image.height - text_height) // 2) + elif position == "right": + position = (image.width - text_width, (image.height - text_height) // 2) + elif position == "center": + position = ((image.width - text_width) // 2, (image.height - text_height) // 2) + elif position == "top": + position = ((image.width - text_width) // 2, 0) + elif position == "bottom": + position = ((image.width - text_width) // 2, image.height - text_height) + elif position == "top left corner": + position = (0, 0) + elif position == "top right corner": + position = (image.width - text_width, 0) + elif position == "bottom left corner": + position = (0, image.height - text_height) + elif position == "bottom right corner": + position = (image.width - text_width, image.height - text_height) + elif position == "bottom left corner 9/10": + position = (0, image.height * 9 // 10 - text_height) + + # 在图片上绘制文本 + draw.multiline_text(position, wrapped_text, font=font, fill=text_color, align=text_position) + # 保存合成后的图片 + image.save(output_path) + # 关闭图片 + # image.close() \ No newline at end of file diff --git a/src/clover_image/delete_file.py b/src/clover_image/delete_file.py new file mode 100644 index 0000000..9260815 --- /dev/null +++ b/src/clover_image/delete_file.py @@ -0,0 +1,10 @@ +import os + + +async def delete_file(file_path): + try: + os.remove(file_path) + except FileNotFoundError: + print(f"文件 {file_path} 不存在。") + except Exception as e: + print(f"删除文件时发生错误: {e}") \ No newline at end of file diff --git a/src/clover_image/download_image.py b/src/clover_image/download_image.py new file mode 100644 index 0000000..7b12c79 --- /dev/null +++ b/src/clover_image/download_image.py @@ -0,0 +1,17 @@ +import requests + +def download_image(url,file_path): + """ + 下载图片 + :param url: + :param file_path: + :return: + """ + try: + response = requests.get(url, stream=True) + response.raise_for_status() + with open(file_path, 'wb') as file: + for chunk in response.iter_content(chunk_size=8192): + file.write(chunk) + except requests.RequestException as e: + print(f"下载图片时出错: {e}") \ No newline at end of file diff --git a/src/clover_image/get_image.py b/src/clover_image/get_image.py new file mode 100644 index 0000000..e8407f4 --- /dev/null +++ b/src/clover_image/get_image.py @@ -0,0 +1,33 @@ +import os +import random +import requests + +from src.configs.path_config import image_local_path +from src.configs.api_config import smms_token,smms_image_upload_history,ju_he_token,ju_he_image_list + +"""本地图片""" +def get_image_names(): + image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] # 定义常见的图片文件扩展名 + image_names = [] + for root, dirs, files in os.walk(image_local_path): + for file in files: + if any(file.endswith(ext) for ext in image_extensions): # 检查文件是否是图片文件 + image_names.append(file) + random.choice(image_names) # 随机选取一张图片 + local_image_path = image_local_path + '/' + random.choice(image_names) # 随机选取一张图片的路径 + return local_image_path + +""" sm.ms 图床""" +def get_smms_image_url(): + # 定义请求的参数 + data = requests.get(smms_image_upload_history, headers={'Authorization': smms_token}, params={"page": "1"}).json().get('data') + urls = [item['url'] for item in data] + random_url = random.choice(urls) + return random_url + +"""聚合图床""" +def get_juhe_image_url(): + # 定义请求的参数 + params = {"token": ju_he_token,"f": "json","categories": "猫羽雫","page": 1, "size": 400} + random_url = random.choice(requests.get(ju_he_image_list, params=params).json().get('docs', [])).get('url') + return random_url diff --git a/src/clover_image/qq_image.py b/src/clover_image/qq_image.py new file mode 100644 index 0000000..27385f6 --- /dev/null +++ b/src/clover_image/qq_image.py @@ -0,0 +1,44 @@ +import os + +import requests + +from src.configs.path_config import image_local_qq_image_path +from src.configs.api_config import app_id,bot_account + + + +"""获取QQ头像""" +def download_qq_image(member_open_id): + if not os.path.exists(image_local_qq_image_path): + os.makedirs(image_local_qq_image_path) + + save_path = image_local_qq_image_path + '/' + member_open_id + '.jpg' + size = 640 #尺寸 40、100、140、640 + url = f"https://q.qlogo.cn/qqapp/{app_id}/{member_open_id}/{size}" + response = requests.get(url) # 发送 GET 请求获取图片资源 + if response.status_code == 200: # 判断请求是否成功 + with open(save_path, 'wb') as file: # 以二进制写入模式打开文件 + file.write(response.content) # 将响应内容写入文件 + return save_path + +"""获取QQ头像""" +def download_qq_image_by_account(account): + if not os.path.exists(image_local_qq_image_path): + os.makedirs(image_local_qq_image_path) + if account is None: + account = bot_account + save_path = image_local_qq_image_path + '/' + account + '.jpg' + size = 640 # 尺寸 40、100、140、640 + url = f"https://q2.qlogo.cn/headimg_dl?dst_uin={account}&spec={size}" + response = requests.get(url) # 发送 GET 请求获取图片资源 + if response.status_code == 200: # 判断请求是否成功 + with open(save_path, 'wb') as file: # 以二进制写入模式打开文件 + file.write(response.content) # 将响应内容写入文件 + return save_path + +"""删除QQ头像""" +def qq_image_delete(): + for root, dirs, files in os.walk(image_local_qq_image_path): + for file in files: + file_path = os.path.join(root, file) + os.remove(file_path) \ No newline at end of file diff --git a/src/clover_image/rua.py b/src/clover_image/rua.py new file mode 100644 index 0000000..d920b94 --- /dev/null +++ b/src/clover_image/rua.py @@ -0,0 +1,65 @@ +import os +from PIL import Image, ImageDraw + +from src.configs.path_config import image_local_qq_image_path,rua_png + + +""" rua 头动图生成""" +class rua(): + def __init__(self, img_file): + self.author = Image.open(img_file) + + def add_png(self, png_d): + # 重置图片大小 + author = self.author.resize((png_d[0], png_d[1] - png_d[2])) + + # 载入素材 + rua_p1 = Image.open(png_d[3]) + + # 创建背景模板 + rua_png1 = Image.new('RGBA', (110, 110), (255, 255, 255, 255)) + + # 使用预定义的参数:jd,合成一帧的样例 + rua_png1.paste(author, (110 - png_d[0], 110 - png_d[1] + png_d[2]), author) + rua_png1.paste(rua_p1, (0, 110 - png_d[1] - png_d[2]), rua_p1) + return rua_png1 + + def add_gif(self): + + # 获取素材列表 + pst = os.listdir(rua_png) + for i in range(len(pst)): + pst[i] = rua_png + pst[i] + + # 预调试好的参数,传入素材列表 + jd = [[90, 90, 5, pst[0]], + [90, 87, 5, pst[2]], + [90, 84, 10, pst[3]], + [90, 81, 8, pst[4]], + [90, 78, 5, pst[5]], + [90, 75, 5, pst[6]], + [90, 72, 8, pst[7]], + [90, 74, 8, pst[8]], + [90, 77, 9, pst[9]], + [90, 80, 8, pst[1]]] + + # 重置要生成的图片大小 + self.author = self.author.resize((90, 90)) + + # 绘制模板 + alpha_layer = Image.new('L', (90, 90), 0) + draw = ImageDraw.Draw(alpha_layer) + draw.ellipse((0, 0, 90, 90), fill=255) + self.author.putalpha(alpha_layer) + + # gif列表 + gifs = [] + for i in range(len(jd)): + # 将参数传递给生成方法 + # 添加到gif列表 + gifs.append(self.add_png(jd[i])) + + # 文件名,是否保存所有,图片列表,fps/ms + gifs[0].save(image_local_qq_image_path + '/rua.gif', "GIF", save_all=True, append_images=gifs, duration=35, loop=0) + self.author.close() + return image_local_qq_image_path + '/rua.gif' \ No newline at end of file diff --git a/src/clover_image/s.png b/src/clover_image/s.png new file mode 100644 index 0000000..1bb308d Binary files /dev/null and b/src/clover_image/s.png differ diff --git a/src/clover_image/search_image_by_image.py b/src/clover_image/search_image_by_image.py new file mode 100644 index 0000000..6564666 --- /dev/null +++ b/src/clover_image/search_image_by_image.py @@ -0,0 +1,79 @@ +import requests + + +def saucenao_search(image_path=None, image_url=None, api_key='your_api_key', numres=5): + """ + 使用 SauceNAO API 进行以图搜图 + + :param image_path: 本地图片的文件路径,若提供图片 URL 则此参数可省略 + :param image_url: 图片的网络 URL,若提供本地图片路径则此参数可省略 + :param api_key: SauceNAO API Key + :param numres: 要返回的搜索结果数量 + :return: 搜索结果的 JSON 数据 + """ + base_url = 'https://saucenao.com/search.php' + params = { + 'output_type': 2, # 输出类型为 JSON + 'numres': numres, # 返回的结果数量 + 'api_key': api_key + } + + if image_url: + params['url'] = image_url + elif image_path: + files = {'file': open(image_path, 'rb')} + response = requests.post(base_url, params=params, files=files) + else: + raise ValueError("url错误") + + if image_url: + response = requests.get(base_url, params=params) + + if response.status_code == 200: + return response.json() + else: + print(f"请求失败,状态码: {response.status_code}") + return None + + +def parse_saucenao_result(result): + """ + 解析 SauceNAO 的搜索结果 + """ + if not result or 'results' not in result: + print("未找到有效的搜索结果。") + return + + print(result) + for index, item in enumerate(result['results'], start=1): + header = item['header'] + data = item['data'] + + similarity = header.get('similarity', '未知') + thumbnail = header.get('thumbnail', '未知') + title = data.get('title', '未知') + author = data.get('member_name', data.get('author_name', '未知')) + ext_urls = data.get('ext_urls', []) + pixiv_id = data.get('pixiv_id', '未知') + + print(f"结果 {index}:") + print(f" 相似度: {similarity}%") + print(f"预览图{thumbnail} ") + print(f" 标题: {title}") + print(f" 作者: {author}") + if ext_urls: + print(f" 来源链接: {ext_urls[0]}") + else: + print(" 来源链接: 未知") + print(f"pixiv_id:{pixiv_id}") + print() + +if __name__ == "__main__": + # 若使用本地图片,提供图片路径 + image_path = 's.png' + # 若使用网络图片,提供图片 URL + # image_url = 'https://example.com/your_image.jpg' + api_key = 'b2f961a88d854dc457a235c55d8486a764e8ff7d' + result = saucenao_search(image_path=image_path, api_key=api_key) + if result: + parse_saucenao_result(result) \ No newline at end of file diff --git a/src/clover_lightnovel/html_to_img.py b/src/clover_lightnovel/html_to_img.py new file mode 100644 index 0000000..ebecd23 --- /dev/null +++ b/src/clover_lightnovel/html_to_img.py @@ -0,0 +1,51 @@ +import os +from datetime import datetime +from os import getcwd +from pathlib import Path + +from nonebot_plugin_htmlrender import template_to_pic +from playwright.async_api import async_playwright + +from src.configs.path_config import light_novel_path +import src.clover_lightnovel.wenku8 as Wenku8 + + +async def save_img(data: bytes): + + """ + 保存日报图片 + :param data: + :return: + """ + file_path = light_novel_path + f"{datetime.now().date()}.png" + with open(file_path, "wb") as file: + file.write(data) + +async def get_ln_image(): + now = datetime.now() + file = Path() / light_novel_path / f"{now.date()}.png" + if os.path.exists(file): + with file.open("rb") as image_file: + return image_file.read() + + await Wenku8.login() + await Wenku8.get_books() + + async with async_playwright() as p: + browser = await p.chromium.launch() + + image_bytes = await template_to_pic( + template_path=getcwd() + "/src/clover_lightnovel/", + template_name="output1.html", + templates={"data": None}, + pages={ + "viewport": {"width": 578, "height": 578}, + "base_url": f"file://{getcwd()}", + }, + wait=2, + ) + await save_img(image_bytes) + await browser.close() + return image_bytes + + diff --git a/src/clover_lightnovel/res/font/NotoSansSC-Bold.otf b/src/clover_lightnovel/res/font/NotoSansSC-Bold.otf new file mode 100644 index 0000000..172eb67 Binary files /dev/null and b/src/clover_lightnovel/res/font/NotoSansSC-Bold.otf differ diff --git a/src/clover_lightnovel/res/font/NotoSansSC-Regular.otf b/src/clover_lightnovel/res/font/NotoSansSC-Regular.otf new file mode 100644 index 0000000..d350ffa Binary files /dev/null and b/src/clover_lightnovel/res/font/NotoSansSC-Regular.otf differ diff --git a/src/clover_lightnovel/res/font/SSFangTangTi.ttf b/src/clover_lightnovel/res/font/SSFangTangTi.ttf new file mode 100644 index 0000000..a8b5c2f Binary files /dev/null and b/src/clover_lightnovel/res/font/SSFangTangTi.ttf differ diff --git a/src/clover_lightnovel/style.css b/src/clover_lightnovel/style.css new file mode 100644 index 0000000..869de19 --- /dev/null +++ b/src/clover_lightnovel/style.css @@ -0,0 +1,759 @@ +@font-face { + font-family: "Noto Sans SC B"; + src: url("./res/font/NotoSansSC-Bold.otf") format("opentype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Noto Sans SC"; + src: url("./res/font/NotoSansSC-Regular.otf") format("opentype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "SSFangTangTi"; + src: url("./res/font/SSFangTangTi.ttf"); +} + +/* basic */ +*{ + margin: 0px; + padding: 0px; +} + +body{ + background: transparent; + text-align: center; + font: 12px/120% 宋体,Verdana,Arial,sans-serif; +} + +a{ + color: #4a4a4a; + text-decoration: none; + background-color: transparent; +} + +a:hover{ + color: #0033ff; +} + +span{ + line-height: 120%; +} + +p{ + line-height: 150%; +} + +h1, h2, h3, h4, h5, h6{ + font-size: 16px; + line-height: 150%; +} + +img{ + border: 0px; +} + +div{ + text-align: left; +} + +hr{ + height: 1px; + border: 1px solid #a4cded; + clear: both; + margin: 5px 0px; +} + +ul{ + list-style: none; + clear: both; + text-align: left; +} + +li{ + line-height: 150%; +} + +/* table */ +table{ + text-align: left; + font: 12px/120% 宋体,Verdana,Arial,sans-serif; +} + +table td{ +} + +table.fix{ + table-layout: fixed; +} + +table.fix td{ + white-space:nowrap; + overflow: hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; +} + +table.grid{ + border-collapse: collapse; + border: 1px solid #a4cded; + padding: 3px; + margin: auto; +} + +table.grid caption, .gridtop{ + border: 1px solid #a4cded; + background: #e9f1f8; + background-image: url("image/caption_bg.gif"); + vertical-align: middle; + text-align: center; + color:#054e86; + font-weight: bold; + font-size: 14px; + margin: auto; + padding-top: 5px; + padding-bottom: 5px; +} + +table.grid th, .head{ + border: 1px solid #a4cded; + background: #f0f7ff; + color:#054e86; + text-align: center; + font-weight: bold; + font-size: 12px; + padding-top: 5px; + padding-bottom: 5px; +} + +table.grid td{ + border: 1px solid #a4cded; + background-color: #ffffff !important; + padding-top: 4px; + padding-bottom: 4px; +} + +table.hide, table.hide th, table.hide td{ + border: 0; +} + +/* table add-ons */ + +.title{ + background: #e9f1f8; + text-align: center; + padding: 3px; + color:#054e86; + font-weight: bold; + font-size: 14px; +} + +.even{ + background: #ffffff; + padding: 3px; +} + +.odd{ + background: #ffffff; + padding: 3px; +} + +.foot{ + background: #f0f7ff; + padding: 3px; + text-align: center; +} + +.bottom{ + height: 9px; + background: #b7b785; +} + + +/* form */ + +form{} + +input{} + +.text{ + border: 1px solid #a4cded; + background: #ffffff; + color: #054e86; + height: 18px; +} + +.textarea{ + border: 1px solid #a4cded; + background: #ffffff; + color: #054e86; +} + +.button{ + background: #ddf2ff; + border: 1px solid #a4cded; + height: 20px; +} + +.checkbox, .radio{border-width: 0px;} + +.select{height: 20px;} +/* structure */ + +#wrapper{ +background:url(image/tabbg1_1.gif)} + +#left{ + float: left; + width: 185px; + margin-right:6px; +} + +#right{ + float: right; + width: 185px; +} + +#centers{ + float: left; + width: 578px; +} + +#centerm{ + float: left; + width: 768px; +} + +#centerl{ + float: left; + width: 960px; +} + +#content{ + +} + +.main{ + width: 960px; + clear: both; + text-align: center; + margin-left: auto; + margin-right: auto; + margin-top:3px; +} + +.m_top{ + line-height: 27px; + height: 27px; + background-image: url("image/m_top_bg.gif"); + background-repeat: repeat-x; + margin-top:0px; +} + +.m_head{ + height: 90px; + margin-top: 10px; + margin-bottom: 10px; +} + +.h_logo{ + float:left; + width:230px; +} + +.h_banner{ + float:left; +} + +.h_link{ + float:right; + width:90px; + padding-top:6px; +} + +.m_menu{ + background:#55a0ff; + height:22px; + border-top:1px solid #e4e4e4; + border-bottom:1px solid #e4e4e4; + padding-top:3px; + margin-bottom:3px; +} + +.m_foot{ + text-align:center; + padding: 20px 0px; + margin-top:3px; + margin-bottom:10px; + border-top: 1px dashed #A4CDED; + border-bottom: 1px dashed #A4CDED; +} + +.blocktop{ + border: 1px solid #a4cded; + margin: 8px; + width: 222px; + float: left; +} + +.blockcaption{ + background: #e9f1f8; + background-image: url("image/caption_bg.gif"); + vertical-align: middle; + text-align: center; + color:#054e86; + font-weight: bold; + font-size: 14px; + margin: auto; + padding-top: 5px; + padding-bottom: 5px; +} + +.block{ + // border: 1px solid #a4cded; + // margin-bottom: 5px; + width: 600px; +} + +.blocktitle{ + border-top: 2px solid #ffffff; + border-bottom: 1px solid #ffffff; + border-left: 2px solid #ffffff; + border-right: 1px solid #ffffff; + font-weight: bold; + font-size: 14px; + background: #45667d; + color: #FFFAFA; + height: 26px; + line-height: 26px; + padding-left: 10px; + font-family: "Noto Sans SC B"; +} + +.blockcontent{ + border-top: 1px solid #a3bee8; + padding: 3px; + background-color: #edf8ff; + border-radius: 0px; + padding: 10px; + font-family: "Noto Sans SC B"; +} +.blockcontenttop{ + border-top: 1px solid #a3bee8; + border-bottom: 1px solid #a3bee8; + padding: 3px; +} + +.blocknote{ + border-top: 1px solid #a4cded; + padding: 3px; + text-align: center; + background: #f0f7ff; + line-height: 150%; +} + +.blocktitle span0{ + position: relative; + bottom: -5px; + border-top: 1px solid #a4cded; + border-left: 1px solid #a4cded; + border-right: 1px solid #a4cded; + background: #ffffff; + padding: 3px 6px 3px 6px; + color: #c42205; + height: 22px; + line-height: 22px; +} + +.blocktitle .txt{ + background-image: url("image/title_l.gif"); + background-repeat: no-repeat; + color: #0049A0; + float: left; + font-size: 13px; + font-weight: bold; + line-height: 20px; + padding-bottom: 0px; + padding-left: 16px; + padding-right: 8px; + padding-top: 7px; +} + +.blocktitle .txtr{ + background-image: url("image/title_r.gif"); + background-repeat: no-repeat; + float: left; + height: 27px; + width: 7px; +} + +.gameblocktop{ + border: 1px solid #a4cded; + margin: 10px; + width: 216px; + float: left; +} + +.gameblockcontent{ + border-top: 1px solid #a3bee8; + padding: 3px 8px; +} + +.appblocktop{ + border: 1px solid #a4cded; + margin: 10px; + width: 938px; + float: left; +} +.appblockcaption{ + background: #e9f1f8; + background-image: url("image/caption_bg.gif"); + vertical-align: middle; + text-align: left; + color:#054e86; + font-weight: bold; + font-size: 14px; + margin: auto; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 10px; +} + +.appblockcontent{ + border-top: 1px solid #a3bee8; + padding-left: 10px; +} + +#left .blocktitle, #right .blocktitle{ + border: 0px; + background-image: url("image/title_bg.gif"); + background-repeat: repeat-x; + height: 27px; +} + +#left .blockcontent, #right .blockcontent{ + border: 0px; + background: #ffffff; +} + +/* custom */ + +.ultop li{list-style: decimal inside; margin: 3px 4px; border-bottom: 1px dashed #d8e4ef; color: #1b74bc;white-space:nowrap;} +.ultop li a{color: #c42205;} +.ultops li{ margin: 3px 4px; border-bottom: 1px dashed #d8e4ef; color: #1b74bc;white-space:nowrap;} +.ultops li a{color: #c42205;} +.ulitem li{list-style: circle inside; margin-left: 3px;} +.ulrow li{padding:3px;} +.ulrowlink li{padding:0px 1px;} +.ulcenter li{text-align: center;} +.ulmul{overflow: hidden;} + +.fix, .lm{white-space:nowrap; text-overflow:ellipsis; -o-text-overflow:ellipsis; overflow: hidden;} +.fl{float:left;} +.fr{float:right;} +.cl{clear:left;} +.cr{clear:right;} +.cb{clear:both;} +.tl{text-align:left;} +.tc{text-align:center;} +.tr{text-align:right;white-space:nowrap;overflow: hidden;} +.more{text-align: right;} + +.c_title{ + width: 100%; + text-align: center; + font-weight: bold; + font-size: 16px; + line-height: 200%; +} + +.c_head{ + line-height: 150%; +} + +.c_content{ + font-size: 14px; + line-height: 150%; +} + +.c_foot{ + line-height: 150%; +} + +.c_label{ + font-weight: bold; +} + +.c_value{ +} + +/* attention */ + +.hottext, a.hottext{color: #ff0000;} +.poptext, a.poptext{color: #c42205;} +.notetext, a.notetext{color: #1979cc;} +.errortext, a.errortext{color: #ff0000;} + +a.btnlink{color: #535353; background: #ffffff; border:0px solid #a4cded; height:16px; padding: 2px 10px 0px 10px;} +a.btnlink:hover{background: #fffff;} + +a.btnlink1{color: #535353; background: #fffff; border:0px solid #a4cded; height:16px; padding: 2px 10px 0px 10px;} +a.btnlink1:hover{background: #fffff;} + +a.btnlink2{color: #535353; background: #DDF2FF; border:1px solid #a4cded; height:16px; padding: 2px 10px 0px 10px;} +a.btnlink2:hover{background: #CCCCCC;} + +/* interface */ + +.jieqiQuote, .jieqiCode, .jieqiNote{ + border: #000000 1px solid; + padding: 2px; + font-size: 12px; + color: #000000; + background-color: #a4cded; +} + +.divbox{ + border: 1px solid #a4cded; + margin-bottom: 3px; + text-align: center; +} + +.textbox{ + border: 1px solid #a4cded; + padding: 5px; + margin: 3px; + line-height: 150%; +} + +.popbox{ + position:absolute; + width:190px !important; + height:110px !important; + width:200px; + height:120px; + border: 1px solid #a4cded; + background: #f0f7ff; + color: #ff0000; + font-size: 12px; + line-height:120%; + padding: 3px; + display:none; + z-index:9999; +} + +#tips { + border: 1px solid #a4cded; + padding: 3px; + display: none; + background: #f0f7ff; + position: absolute; + z-index: 2000; +} + +.tablist ul{height:25px; margin:0px 0px 0px 10px; padding:0px;} +.tablist li{float:left; height:24px; list-style:none; margin-right:3px;} +.tablist li a{float:left; height:24px; line-height:24px; padding:0px 10px; display:block; background:#f0f7ff; text-decoration:none; color:#000000; border:1px solid #a4cded; border-bottom:none; } +.tablist li a.selected{ background:#ffffff; height:25px; position:relative; margin-bottom:-1px;} +.tabcontent{clear:both; border:1px solid #a4cded; padding:10px;} + +.pages{ + padding: 5px 0px; +} +.pagelink{ + border: 1px solid #a4cded; + float: right; + background: #f0f7ff; + line-height:24px; + padding:0; +} +.pagelink a, .pagelink strong, .pagelink em, .pagelink kbd, .pagelink a.first, .pagelink a.last, .pagelink a.prev, .pagelink a.next, .pagelink a.pgroup, .pagelink a.ngroup{ + float: left; + padding: 0 6px; +} +.pagelink a:hover{background-color: #ffffff; } +.pagelink strong{font-weight: bold; color: #ff6600; background: #e9f1f8;} +.pagelink kbd{height:24px; border-left: 1px solid #a4cded;} +.pagelink em{height:24px; border-right: 1px solid #a4cded; font-style:normal;} +.pagelink input{border: 1px solid #a4cded; color: #054e86; margin-top:1px; height: 18px;} + +/* menu */ + +.nav { + position: relative; + background: url("image/nav_bg.png") no-repeat 0 -36px; + margin-bottom:3px; +} +.navinner { + background: url("image/nav_bg.png") no-repeat 100% -72px; +} +.navlist { + height: 36px; + overflow: hidden; + margin: 0px; + background: url("image/nav_bg.png") repeat-x 0 0; +} +.nav li { + height: 36px; + line-height: 36px; + float: left; + display: inline; + margin: 0 0 0 -2px; + padding: 0 4px 0 6px; + background: url("image/nav_bg.png") no-repeat 0 -108px; +} +.nav a { + display: block; + width: 85px; + text-align: center; + font-size: 120%; +} +.nav a:link, .nav a:visited { + color: #fff;text-decoration:none; +} +.nav a.current, .nav a:hover, .nav a:active { + color: #fff; + font-weight: bold; + background: url("image/nav_bg.png") no-repeat 50% -144px; +} +.subnav { + position: absolute; + top: 40px; + left: 0; + float: left; + height: 27px; + white-space: nowrap; + line-height: 27px; + background: url("image/nav_bg.png") no-repeat 0 -180px; +} +* html .subnav { + margin: 0 10px 0 -10px; /* IE 6 and below */ +} +.subnav p { + padding: 0px 10px; + background: url("image/nav_bg.png") no-repeat 100% -234px; +} +.subnav p span { + display: block; + height: 27px; + line-height: 27px; + background: url("image/nav_bg.png") repeat-x 0 -207px; +} +.subnav p.pointer { + position: absolute; + top: -4px; + left: 0; + height: 5px; + width: 11px; + padding: 0; + margin-left: 20px; + text-indent: -999em; + background: url("image/nav_bg.png") repeat-x 0 -261px; +} +.subnav a { + display: inline; + padding: 0; + font-size: 100%; +} +[class~="subnav"] a { + padding: 0 3px; +} +.subnav, .subnav a:link, .subnav a:visited { + color: #235e99; +} +.subnav a:hover, .subnav a:active { + color: #235e99; +} +.subnav a:hover, .subnav a:active { + font-weight: normal; + background: none; + border-bottom: 1px solid; +} +/* subnav position and pointer position */ +#subnav1 { left: 80px; } +#subnav2 { left: 170px; } +#subnav3 { left: 260px; } +#subnav4 { left: 350px; } +#subnav0, #subnav5, #subnav6, #subnav7, #subnav8, #subnav9 { + left: auto; + right: 0px; +} + +#subnav0 .pointer { left: 100px; } +#subnav1 .pointer, +#subnav2 .pointer { left: 38px; } +#subnav3 .pointer, +#subnav4 .pointer { left: 30px; } +#subnav5 .pointer { left: auto; right: 450px; } +#subnav6 .pointer { left: auto; right: 350px; } +#subnav7 .pointer { left: auto; right: 260px; } +#subnav8 .pointer { left: auto; right: 160px; } +#subnav9 .pointer { left: auto; right: 70px; } + +#subnav1, #subnav2, #subnav3, #subnav4 { + min-width: 110px; +} +#subnav5 { min-width: 340px; } +#subnav6 { min-width: 240px; } +#subnav7 { min-width: 130px; } +.disable { display: none; } + + +/*ajax框*/ +.ajaxtip{ + position:absolute; + border: 1px solid #a3bee8; + background: #f0f7ff; + color: #ff0000; + font-size: 12px; + line-height:120%; + padding: 3px; + z-index:1000; +} +#tips { + border: 1px solid #a3bee8; + padding: 3px; + display: none; + background: #f0f7ff; + position: absolute; + z-index: 2000; +} +#dialog{ + position:absolute; + top:0px; + left:0px; + border: 5px solid #8bcee4; + background: #f1f5fa; + font-size: 12px; + line-height:120%; + padding: 20px 10px 10px 10px; + visibility: hidden; +} +#mask{ + position:absolute; + top:0px; + left:0px; + background: #777777; + filter: Alpha(opacity=30); + opacity: 0.3; +} + +.userinfo_001{background:url(image/userinfo.gif) 0px 0px no-repeat; padding-left:16px;} +.userinfo_002{background:url(image/userinfo.gif) 0px -16px no-repeat; padding-left:16px;} +.userinfo_003{background:url(image/userinfo.gif) 0px -34px no-repeat; padding-left:16px;} +.userinfo_004{background:url(image/userinfo.gif) 0px -54px no-repeat; padding-left:16px;} +.userinfo_005{background:url(image/userinfo.gif) 0px -73px no-repeat; padding-left:16px;} +.userinfo_006{background:url(image/userinfo.gif) 0px -94px no-repeat; padding-left:16px;} +.userinfo_007{background:url(image/userinfo.gif) 0px -113px no-repeat; padding-left:16px;} +.userinfo_008{background:url(image/userinfo.gif) 0px -133px no-repeat; padding-left:16px;} +img.avatar{ + border: 0px; +} +img.avatars{ + border: 1px solid #dddddd; +} \ No newline at end of file diff --git a/src/clover_lightnovel/wenku8.py b/src/clover_lightnovel/wenku8.py new file mode 100644 index 0000000..3585ac4 --- /dev/null +++ b/src/clover_lightnovel/wenku8.py @@ -0,0 +1,107 @@ +from os import getcwd + +import requests +from bs4 import BeautifulSoup +from src.configs.api_config import wenku8_username, wenku8_password, proxy_api + + + +# 登录页面的URL +login_url = 'https://www.wenku8.net/login.php?jumpurl=http%3A%2F%2Fwww.wenku8.net%2Findex.php' +index_url = 'https://www.wenku8.net/index.php' + +headers = { + 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', + 'Connection': 'close', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.41' +} + +# 登录表单数据 +login_data = { + 'username': wenku8_username, + 'password': wenku8_password, + 'usecookie': '0', + 'action': 'login' +} + +def get_proxy(headers): + #proxy_url可通过多米HTTP代理网站购买后生成代理api链接,每次请求api链接都是新的ip + proxy_url = proxy_api + aaa=requests.get(proxy_url, headers=headers).text + proxy_host = aaa.splitlines()[0] + print('代理IP为:'+proxy_host) + #proxy_host='117.35.254.105:22001' + #proxy_host='192.168.0.134:1080' + proxy = { + 'http': 'http://'+proxy_host, + 'https': 'http://'+proxy_host + } + return proxy + +async def login(): + # 发送登录请求 + with requests.Session() as session: + proxy = get_proxy(headers) + # 注意:这里使用了Session对象来保持会话状态 + login_response = session.post(login_url, data=login_data, headers=headers, proxies=proxy) + + # 检查登录是否成功(根据实际需求调整) + if login_response.status_code == 200: + # 登录成功后,Session对象已经自动保存了Cookie + # 可以直接使用该Session对象访问受保护的页面 + print("登录成功!") + # 获取 Cookie + cookies = session.cookies + + # 保存 Cookie 到文件 + with open('wenku8.cookie', 'w') as f: + for cookie in cookies: + f.write(f"{cookie.name}={cookie.value}; ") + print("Cookie 保存成功!") + else: + print("登录失败,状态码:", login_response.status_code) + + +async def get_books(): + with open('wenku8.cookie', 'r') as f: + cookie = f.read() + headers1 = { + 'Connection': 'close', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.41', + 'Cookie': cookie + } + proxy = get_proxy(headers1) + response = requests.get(index_url, headers=headers1, proxies=proxy) + print(response) + html = response.content.decode('gbk') + soup = BeautifulSoup(html, 'html.parser') + orders = soup.find_all(name='div', class_='block') + head = """ + + + + + + 轻小说文库 - 最新最全的日本动漫轻小说在线阅读与下载基地 + + + + + + + + + + + """ + # print(orders[7].text) + with open(getcwd() + "/src/clover_lightnovel/output1.html", 'w', encoding='utf-8') as file: + file.write(head + str(orders[7]).replace('(查看 这本轻小说真厉害!2025 TOP榜单)', '') + str(orders[8]) + str(orders[9]) + str(orders[10])) + + +if __name__ == '__main__': + login() + get_books() diff --git a/src/clover_music/cloud_music/agent.py b/src/clover_music/cloud_music/agent.py new file mode 100644 index 0000000..28a62b2 --- /dev/null +++ b/src/clover_music/cloud_music/agent.py @@ -0,0 +1,61 @@ +# -*- coding: UTF-8 -*- + +import random +import execjs +agent = [ + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/57.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', + +] + +# 获取浏览器认证头 +def get_user_agents(): + return random.choice(agent) +# 读取js +def djs(js): + f = open(js, 'r', encoding='utf-8') + jst = '' + while True: + readline = f.readline() + if readline: + jst += readline + else: + break + return jst +def get_login_js(): + return djs('src/clover_music/cloud_music/jsdm.js') + +def get_param_js(): + return djs('src/clover_music/cloud_music/param.js') + +# 获取ptqrtoken +def ptqrtoken(qrsign): + # 加载js + execjs_execjs = execjs.compile(get_login_js()) + return execjs_execjs.call('hash33', qrsign) +# 获取UI +def guid(): + # 加载js + execjs_execjs = execjs.compile(get_login_js()) + return execjs_execjs.call('guid') +# 获取g_tk +def get_g_tk(p_skey): + # 加载js + execjs_execjs = execjs.compile(get_login_js()) + return execjs_execjs.call('getToken', p_skey) +# 获取i +def S(): + # 加载js + execjs_execjs = execjs.compile(get_login_js()) + return execjs_execjs.call('S') +# 获取key +def a(): + # 加载js + execjs_execjs = execjs.compile(get_login_js()) + return execjs_execjs.call('a', 16) + +def get_params(id): + execjs_execjs = execjs.compile(get_param_js()) + return execjs_execjs.call('get_music', id) diff --git a/src/clover_music/cloud_music/cloud_music.py b/src/clover_music/cloud_music/cloud_music.py new file mode 100644 index 0000000..a851060 --- /dev/null +++ b/src/clover_music/cloud_music/cloud_music.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +import os +import qrcode +import base64 +import codecs +import json +import requests +from io import BytesIO +from random import Random +from Crypto.Cipher import AES +from graiax import silkcoder +import src.clover_music.cloud_music.agent as agent + + +requests.packages.urllib3.disable_warnings() +headers = {'User-Agent': agent.get_user_agents(), 'Referer': 'https://music.163.com/'} + + +# 解密params和encSecKey值 +def keys(key): + while len(key) % 16 != 0: + key += '\0' + return str.encode(key) + +#登录加密 +def AES_aes(t, key, iv): + def p(s): return s + (AES.block_size - len(s) %AES.block_size) * chr(AES.block_size - len(s) % AES.block_size) + encrypt = str(base64.encodebytes(AES.new( keys(key), AES.MODE_CBC,keys(iv)).encrypt(str.encode(p(t)))),encoding='utf-8') + return encrypt + +def RSA_rsa(i, e, f): + return format(int(codecs.encode( + i[::-1].encode('utf-8'), 'hex_codec'), 16) ** int(e, 16) % int(f, 16), 'x').zfill(256) + +# 获取的参数 +key = agent.S() # i6c的值 +d = str({'key': key, 'type': "1", 'csrf_token': ""}) +e = "010001" # (["流泪", "强"])的值 +f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" +g = "0CoJUm6Qyw8W8jud" # (["爱心", "女孩", "惊恐", "大笑"])的值 +iv = "0102030405060708" # 偏移量 +i = agent.a() # 随机生成长度为16的字符串 + + +def login_params(u): + if u is None: + return AES_aes(AES_aes(d, g, iv), i, iv) # g 和 i 都是key代替 + else: + return AES_aes(AES_aes(u,g,iv),i,iv) # g 和 i 都是key代替 + +def login_encSecKey(): + return RSA_rsa(i, e, f) + +def get_music(id): + return agent.get_params(id) + + + + +""" +使用二维码登录网易云音乐,需要先获取二维码的key,然后使用该key生成二维码,扫描二维码登录,最后通过登录接口 返回cookie 保存起来 +""" +save_path = os.getcwd()+'/src/clover_music/netease_music' +os.makedirs(save_path, exist_ok=True) +qrcode_path = os.getcwd()+'/src/clover_music' + + +# 判断cookie是否有效 +def netease_cloud_music_is_login(session): + try: + session.cookies.load(ignore_discard=True) + except Exception: + pass + csrf_token = session.cookies.get('__csrf') + if csrf_token is None: + return session, False + else: + try: + loginurl = session.post(f'https://music.163.com/weapi/w/nuser/account/get?csrf_token={csrf_token}',data={'params': login_params(None), 'encSecKey': login_encSecKey()}, headers=headers).json() + if '200' in str(loginurl['code']): + print(loginurl) + print('登录成功') + return session, True + else: + print('登录失败') + return session, False + except BaseException: + return session, False + +# 获取二维码的key +def get_qr_key(session): + url = f"https://music.163.com/weapi/login/qrcode/unikey" + data = {"params": login_params(None),"encSecKey": login_encSecKey()} + response = session.post(url, headers=headers,params=data) + result = json.loads(response.text) + if result.get("code") == 200: + unikey = result.get("unikey") + return unikey + else: + return None + +# 创建 QRCode 对象 +qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) +# 生成二维码 +def create_qr_code(unikey): + # 添加数据 + png_url = f"http://music.163.com/login?codekey={unikey}" + qr.add_data(png_url) + img = qr.make_image() + a = BytesIO() + img.save(a, 'png') + img.save(os.path.join(qrcode_path, 'qrcode.png')) + return qrcode_path + '/qrcode.png' + +# 检查二维码状态是否被扫描 +def check_qr_code(unikey,session): + token_url = f"https://music.163.com/weapi/login/qrcode/client/login?csrf_token=" + u = str({'key': unikey, 'type': "1", 'csrf_token': ""}) + qrcode_data = session.post( token_url,data={'params': login_params(u),'encSecKey': login_encSecKey()},headers=headers).json() + return qrcode_data.get('code') + +def netease_music_search(keyword,session): + url = "http://music.163.com/api/search/get" + params = { + "s": keyword, + "type": 1, # 1 表示搜索歌曲,2 表示搜索专辑,3 表示搜索歌手等 + "limit": 10, # 限制搜索结果的数量 + "offset": 0, # 搜索结果的偏移量,可用于分页 + "sub": "false", + } + response = session.get(url, headers=headers, params=params) + data = response.json() + if "result" in data and "songs" in data["result"]: + songs = data["result"]["songs"] + if songs: + first_song = songs[0] # 获取第一首歌曲 + song_name = first_song["name"] + singer = first_song["artists"][0]["name"] + song_id = first_song["id"] + song_url = f"https://music.163.com/song?id={song_id}" + print(f"搜索结果:{song_name} - {singer}") + print(f"歌曲链接:{song_url}") + return song_id,song_name,singer,song_url + return None, None, None, None + +#仅限于免费歌曲 +# def netease_music_download(song_id,song_name,singer,session): +# if not os.path.exists(save_path): +# os.makedirs(save_path) +# download_url = f"http://music.163.com/song/media/outer/url?br=999000&id={song_id}.mp3" +# response = session.get(download_url, headers=headers) +# if response.status_code == 200: +# print(f"正在下载 {song_name} - {singer} 歌曲...") +# file_path = os.path.join(save_path, f"{song_name}-{singer}.mp3") +# file_name = os.path.basename(f"{song_name}-{singer}.mp3") +# with open(file_path, "wb") as f: +# f.write(response.content) +# output_silk_path = os.path.join(save_path, os.path.splitext(file_name)[0] + ".silk") +# # 使用 graiax-silkcoder 进行转换 +# silkcoder.encode(file_path, output_silk_path) +# return output_silk_path +# else: +# return None + +#所有歌曲都可以下载 +def netease_music_download(song_id,song_name,singer,session): + + if not os.path.exists(save_path): + os.makedirs(save_path) + #获取加密后的歌曲id信息 + result = get_music(song_id) + data = {'params': result['encText'], 'encSecKey': result['encSecKey'],} + download_url = 'https://music.163.com/weapi/song/enhance/player/url/v1?br=999000' + url = session.post(download_url, headers=headers,data=data).json()['data'][0]['url'] + + if url is None: + return -1 + + #下载歌曲 + data = requests.get(url, stream=True) + file_path = os.path.join(save_path, f"{song_name}-{singer}.wav") + file_name = os.path.basename(f"{song_name}-{singer}.wav") + with open(file_path, "wb") as f: + f.write(data.content) + if data.status_code == 200: + with open(file_path, 'wb') as file: + for chunk in data.iter_content(chunk_size=8192): + file.write(chunk) + output_silk_path = os.path.join(save_path, os.path.splitext(file_name)[0] + ".silk") + # 使用 graiax-silkcoder 进行转换 + silkcoder.encode(file_path, output_silk_path,tencent=True,ios_adaptive=True) + return output_silk_path + else: + return None + +def netease_music_delete(): + for root, dirs, files in os.walk(save_path): + for file in files: + file_path = os.path.join(root, file) + os.remove(file_path) + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/clover_music/cloud_music/jsdm.js b/src/clover_music/cloud_music/jsdm.js new file mode 100644 index 0000000..9c04f6b --- /dev/null +++ b/src/clover_music/cloud_music/jsdm.js @@ -0,0 +1,42 @@ +function hash33(t) { + for (var e = 0, i = 0, n = t.length; i < n; ++i) + e += (e << 5) + t.charCodeAt(i); + return 2147483647 & e +} + +function getToken(p_skey) { + var str = p_skey || '', + hash = 5381; + for (var i = 0, len = str.length; i < len; ++i) { + hash += (hash << 5) + str.charCodeAt(i); + } + return hash & 0x7fffffff; +} + +function guid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }).toUpperCase(); +}; + + +function S() { + var e = (new Date).getTime(); + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(t) { + var n = (e + 16 * Math.random()) % 16 | 0; + return e = Math.floor(e / 16), + ("x" === t ? n : 7 & n | 8).toString(16) + }) +} + + +function a(a) { + var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; + for (d = 0; a > d; d += 1) + e = Math.random() * b.length, + e = Math.floor(e), + c += b.charAt(e); + return c +} + diff --git a/src/clover_music/cloud_music/param.js b/src/clover_music/cloud_music/param.js new file mode 100644 index 0000000..4bf0ad6 --- /dev/null +++ b/src/clover_music/cloud_music/param.js @@ -0,0 +1,476 @@ +window = global; +const CryptoJS = require('crypto-js'); + +function RSAKeyPair(a, b, c) { + this.e = biFromHex(a), + this.d = biFromHex(b), + this.m = biFromHex(c), + this.chunkSize = 2 * biHighIndex(this.m), + this.radix = 16, + this.barrett = new BarrettMu(this.m) +} +function twoDigit(a) { + return (10 > a ? "0" : "") + String(a) +} +function encryptedString(a, b) { + for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e; ) + c[e] = b.charCodeAt(e), + e++; + for (; 0 != c.length % a.chunkSize; ) + c[e++] = 0; + for (f = c.length, + g = "", + e = 0; f > e; e += a.chunkSize) { + for (j = new BigInt, + h = 0, + i = e; i < e + a.chunkSize; ++h) + j.digits[h] = c[i++], + j.digits[h] += c[i++] << 8; + k = a.barrett.powMod(j, a.e), + l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix), + g += l + " " + } + return g.substring(0, g.length - 1) +} +function decryptedString(a, b) { + var e, f, g, h, c = b.split(" "), d = ""; + for (e = 0; e < c.length; ++e) + for (h = 16 == a.radix ? biFromHex(c[e]) : biFromString(c[e], a.radix), + g = a.barrett.powMod(h, a.d), + f = 0; f <= biHighIndex(g); ++f) + d += String.fromCharCode(255 & g.digits[f], g.digits[f] >> 8); + return 0 == d.charCodeAt(d.length - 1) && (d = d.substring(0, d.length - 1)), + d +} +function setMaxDigits(a) { + maxDigits = a, + ZERO_ARRAY = new Array(maxDigits); + for (var b = 0; b < ZERO_ARRAY.length; b++) + ZERO_ARRAY[b] = 0; + bigZero = new BigInt, + bigOne = new BigInt, + bigOne.digits[0] = 1 +} +function BigInt(a) { + this.digits = "boolean" == typeof a && 1 == a ? null : ZERO_ARRAY.slice(0), + this.isNeg = !1 +} +function biFromDecimal(a) { + for (var d, e, f, b = "-" == a.charAt(0), c = b ? 1 : 0; c < a.length && "0" == a.charAt(c); ) + ++c; + if (c == a.length) + d = new BigInt; + else { + for (e = a.length - c, + f = e % dpl10, + 0 == f && (f = dpl10), + d = biFromNumber(Number(a.substr(c, f))), + c += f; c < a.length; ) + d = biAdd(biMultiply(d, lr10), biFromNumber(Number(a.substr(c, dpl10)))), + c += dpl10; + d.isNeg = b + } + return d +} +function biCopy(a) { + var b = new BigInt(!0); + return b.digits = a.digits.slice(0), + b.isNeg = a.isNeg, + b +} +function biFromNumber(a) { + var c, b = new BigInt; + for (b.isNeg = 0 > a, + a = Math.abs(a), + c = 0; a > 0; ) + b.digits[c++] = a & maxDigitVal, + a >>= biRadixBits; + return b +} +function reverseStr(a) { + var c, b = ""; + for (c = a.length - 1; c > -1; --c) + b += a.charAt(c); + return b +} +function biToString(a, b) { + var d, e, c = new BigInt; + for (c.digits[0] = b, + d = biDivideModulo(a, c), + e = hexatrigesimalToChar[d[1].digits[0]]; 1 == biCompare(d[0], bigZero); ) + d = biDivideModulo(d[0], c), + digit = d[1].digits[0], + e += hexatrigesimalToChar[d[1].digits[0]]; + return (a.isNeg ? "-" : "") + reverseStr(e) +} +function biToDecimal(a) { + var c, d, b = new BigInt; + for (b.digits[0] = 10, + c = biDivideModulo(a, b), + d = String(c[1].digits[0]); 1 == biCompare(c[0], bigZero); ) + c = biDivideModulo(c[0], b), + d += String(c[1].digits[0]); + return (a.isNeg ? "-" : "") + reverseStr(d) +} +function digitToHex(a) { + var b = 15 + , c = ""; + for (i = 0; 4 > i; ++i) + c += hexToChar[a & b], + a >>>= 4; + return reverseStr(c) +} +function biToHex(a) { + var d, b = ""; + for (biHighIndex(a), + d = biHighIndex(a); d > -1; --d) + b += digitToHex(a.digits[d]); + return b +} +function charToHex(a) { + var h, b = 48, c = b + 9, d = 97, e = d + 25, f = 65, g = 90; + return h = a >= b && c >= a ? a - b : a >= f && g >= a ? 10 + a - f : a >= d && e >= a ? 10 + a - d : 0 +} +function hexToDigit(a) { + var d, b = 0, c = Math.min(a.length, 4); + for (d = 0; c > d; ++d) + b <<= 4, + b |= charToHex(a.charCodeAt(d)); + return b +} +function biFromHex(a) { + var d, e, b = new BigInt, c = a.length; + for (d = c, + e = 0; d > 0; d -= 4, + ++e) + b.digits[e] = hexToDigit(a.substr(Math.max(d - 4, 0), Math.min(d, 4))); + return b +} +function biFromString(a, b) { + var g, h, i, j, c = "-" == a.charAt(0), d = c ? 1 : 0, e = new BigInt, f = new BigInt; + for (f.digits[0] = 1, + g = a.length - 1; g >= d; g--) + h = a.charCodeAt(g), + i = charToHex(h), + j = biMultiplyDigit(f, i), + e = biAdd(e, j), + f = biMultiplyDigit(f, b); + return e.isNeg = c, + e +} +function biDump(a) { + return (a.isNeg ? "-" : "") + a.digits.join(" ") +} +function biAdd(a, b) { + var c, d, e, f; + if (a.isNeg != b.isNeg) + b.isNeg = !b.isNeg, + c = biSubtract(a, b), + b.isNeg = !b.isNeg; + else { + for (c = new BigInt, + d = 0, + f = 0; f < a.digits.length; ++f) + e = a.digits[f] + b.digits[f] + d, + c.digits[f] = 65535 & e, + d = Number(e >= biRadix); + c.isNeg = a.isNeg + } + return c +} +function biSubtract(a, b) { + var c, d, e, f; + if (a.isNeg != b.isNeg) + b.isNeg = !b.isNeg, + c = biAdd(a, b), + b.isNeg = !b.isNeg; + else { + for (c = new BigInt, + e = 0, + f = 0; f < a.digits.length; ++f) + d = a.digits[f] - b.digits[f] + e, + c.digits[f] = 65535 & d, + c.digits[f] < 0 && (c.digits[f] += biRadix), + e = 0 - Number(0 > d); + if (-1 == e) { + for (e = 0, + f = 0; f < a.digits.length; ++f) + d = 0 - c.digits[f] + e, + c.digits[f] = 65535 & d, + c.digits[f] < 0 && (c.digits[f] += biRadix), + e = 0 - Number(0 > d); + c.isNeg = !a.isNeg + } else + c.isNeg = a.isNeg + } + return c +} +function biHighIndex(a) { + for (var b = a.digits.length - 1; b > 0 && 0 == a.digits[b]; ) + --b; + return b +} +function biNumBits(a) { + var e, b = biHighIndex(a), c = a.digits[b], d = (b + 1) * bitsPerDigit; + for (e = d; e > d - bitsPerDigit && 0 == (32768 & c); --e) + c <<= 1; + return e +} +function biMultiply(a, b) { + var d, h, i, k, c = new BigInt, e = biHighIndex(a), f = biHighIndex(b); + for (k = 0; f >= k; ++k) { + for (d = 0, + i = k, + j = 0; e >= j; ++j, + ++i) + h = c.digits[i] + a.digits[j] * b.digits[k] + d, + c.digits[i] = h & maxDigitVal, + d = h >>> biRadixBits; + c.digits[k + e + 1] = d + } + return c.isNeg = a.isNeg != b.isNeg, + c +} +function biMultiplyDigit(a, b) { + var c, d, e, f; + for (result = new BigInt, + c = biHighIndex(a), + d = 0, + f = 0; c >= f; ++f) + e = result.digits[f] + a.digits[f] * b + d, + result.digits[f] = e & maxDigitVal, + d = e >>> biRadixBits; + return result.digits[1 + c] = d, + result +} +function arrayCopy(a, b, c, d, e) { + var g, h, f = Math.min(b + e, a.length); + for (g = b, + h = d; f > g; ++g, + ++h) + c[h] = a[g] +} +function biShiftLeft(a, b) { + var e, f, g, h, c = Math.floor(b / bitsPerDigit), d = new BigInt; + for (arrayCopy(a.digits, 0, d.digits, c, d.digits.length - c), + e = b % bitsPerDigit, + f = bitsPerDigit - e, + g = d.digits.length - 1, + h = g - 1; g > 0; --g, + --h) + d.digits[g] = d.digits[g] << e & maxDigitVal | (d.digits[h] & highBitMasks[e]) >>> f; + return d.digits[0] = d.digits[g] << e & maxDigitVal, + d.isNeg = a.isNeg, + d +} +function biShiftRight(a, b) { + var e, f, g, h, c = Math.floor(b / bitsPerDigit), d = new BigInt; + for (arrayCopy(a.digits, c, d.digits, 0, a.digits.length - c), + e = b % bitsPerDigit, + f = bitsPerDigit - e, + g = 0, + h = g + 1; g < d.digits.length - 1; ++g, + ++h) + d.digits[g] = d.digits[g] >>> e | (d.digits[h] & lowBitMasks[e]) << f; + return d.digits[d.digits.length - 1] >>>= e, + d.isNeg = a.isNeg, + d +} +function biMultiplyByRadixPower(a, b) { + var c = new BigInt; + return arrayCopy(a.digits, 0, c.digits, b, c.digits.length - b), + c +} +function biDivideByRadixPower(a, b) { + var c = new BigInt; + return arrayCopy(a.digits, b, c.digits, 0, c.digits.length - b), + c +} +function biModuloByRadixPower(a, b) { + var c = new BigInt; + return arrayCopy(a.digits, 0, c.digits, 0, b), + c +} +function biCompare(a, b) { + if (a.isNeg != b.isNeg) + return 1 - 2 * Number(a.isNeg); + for (var c = a.digits.length - 1; c >= 0; --c) + if (a.digits[c] != b.digits[c]) + return a.isNeg ? 1 - 2 * Number(a.digits[c] > b.digits[c]) : 1 - 2 * Number(a.digits[c] < b.digits[c]); + return 0 +} +function biDivideModulo(a, b) { + var f, g, h, i, j, k, l, m, n, o, p, q, r, s, c = biNumBits(a), d = biNumBits(b), e = b.isNeg; + if (d > c) + return a.isNeg ? (f = biCopy(bigOne), + f.isNeg = !b.isNeg, + a.isNeg = !1, + b.isNeg = !1, + g = biSubtract(b, a), + a.isNeg = !0, + b.isNeg = e) : (f = new BigInt, + g = biCopy(a)), + new Array(f,g); + for (f = new BigInt, + g = a, + h = Math.ceil(d / bitsPerDigit) - 1, + i = 0; b.digits[h] < biHalfRadix; ) + b = biShiftLeft(b, 1), + ++i, + ++d, + h = Math.ceil(d / bitsPerDigit) - 1; + for (g = biShiftLeft(g, i), + c += i, + j = Math.ceil(c / bitsPerDigit) - 1, + k = biMultiplyByRadixPower(b, j - h); -1 != biCompare(g, k); ) + ++f.digits[j - h], + g = biSubtract(g, k); + for (l = j; l > h; --l) { + for (m = l >= g.digits.length ? 0 : g.digits[l], + n = l - 1 >= g.digits.length ? 0 : g.digits[l - 1], + o = l - 2 >= g.digits.length ? 0 : g.digits[l - 2], + p = h >= b.digits.length ? 0 : b.digits[h], + q = h - 1 >= b.digits.length ? 0 : b.digits[h - 1], + f.digits[l - h - 1] = m == p ? maxDigitVal : Math.floor((m * biRadix + n) / p), + r = f.digits[l - h - 1] * (p * biRadix + q), + s = m * biRadixSquared + (n * biRadix + o); r > s; ) + --f.digits[l - h - 1], + r = f.digits[l - h - 1] * (p * biRadix | q), + s = m * biRadix * biRadix + (n * biRadix + o); + k = biMultiplyByRadixPower(b, l - h - 1), + g = biSubtract(g, biMultiplyDigit(k, f.digits[l - h - 1])), + g.isNeg && (g = biAdd(g, k), + --f.digits[l - h - 1]) + } + return g = biShiftRight(g, i), + f.isNeg = a.isNeg != e, + a.isNeg && (f = e ? biAdd(f, bigOne) : biSubtract(f, bigOne), + b = biShiftRight(b, i), + g = biSubtract(b, g)), + 0 == g.digits[0] && 0 == biHighIndex(g) && (g.isNeg = !1), + new Array(f,g) +} +function biDivide(a, b) { + return biDivideModulo(a, b)[0] +} +function biModulo(a, b) { + return biDivideModulo(a, b)[1] +} +function biMultiplyMod(a, b, c) { + return biModulo(biMultiply(a, b), c) +} +function biPow(a, b) { + for (var c = bigOne, d = a; ; ) { + if (0 != (1 & b) && (c = biMultiply(c, d)), + b >>= 1, + 0 == b) + break; + d = biMultiply(d, d) + } + return c +} +function biPowMod(a, b, c) { + for (var d = bigOne, e = a, f = b; ; ) { + if (0 != (1 & f.digits[0]) && (d = biMultiplyMod(d, e, c)), + f = biShiftRight(f, 1), + 0 == f.digits[0] && 0 == biHighIndex(f)) + break; + e = biMultiplyMod(e, e, c) + } + return d +} +function BarrettMu(a) { + this.modulus = biCopy(a), + this.k = biHighIndex(this.modulus) + 1; + var b = new BigInt; + b.digits[2 * this.k] = 1, + this.mu = biDivide(b, this.modulus), + this.bkplus1 = new BigInt, + this.bkplus1.digits[this.k + 1] = 1, + this.modulo = BarrettMu_modulo, + this.multiplyMod = BarrettMu_multiplyMod, + this.powMod = BarrettMu_powMod +} +function BarrettMu_modulo(a) { + var i, b = biDivideByRadixPower(a, this.k - 1), c = biMultiply(b, this.mu), d = biDivideByRadixPower(c, this.k + 1), e = biModuloByRadixPower(a, this.k + 1), f = biMultiply(d, this.modulus), g = biModuloByRadixPower(f, this.k + 1), h = biSubtract(e, g); + for (h.isNeg && (h = biAdd(h, this.bkplus1)), + i = biCompare(h, this.modulus) >= 0; i; ) + h = biSubtract(h, this.modulus), + i = biCompare(h, this.modulus) >= 0; + return h +} +function BarrettMu_multiplyMod(a, b) { + var c = biMultiply(a, b); + return this.modulo(c) +} +function BarrettMu_powMod(a, b) { + var d, e, c = new BigInt; + for (c.digits[0] = 1, + d = a, + e = b; ; ) { + if (0 != (1 & e.digits[0]) && (c = this.multiplyMod(c, d)), + e = biShiftRight(e, 1), + 0 == e.digits[0] && 0 == biHighIndex(e)) + break; + d = this.multiplyMod(d, d) + } + return c +} +var maxDigits, ZERO_ARRAY, bigZero, bigOne, dpl10, lr10, hexatrigesimalToChar, hexToChar, highBitMasks, lowBitMasks, biRadixBase = 2, biRadixBits = 16, bitsPerDigit = biRadixBits, biRadix = 65536, biHalfRadix = biRadix >>> 1, biRadixSquared = biRadix * biRadix, maxDigitVal = biRadix - 1, maxInteger = 9999999999999998; +setMaxDigits(20), +dpl10 = 15, +lr10 = biFromNumber(1e15), +hexatrigesimalToChar = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"), +hexToChar = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"), +highBitMasks = new Array(0,32768,49152,57344,61440,63488,64512,65024,65280,65408,65472,65504,65520,65528,65532,65534,65535), +lowBitMasks = new Array(0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535); + +!function() { + function a(a) { + var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = ""; + for (d = 0; a > d; d += 1) + e = Math.random() * b.length, + e = Math.floor(e), + c += b.charAt(e); + return c + } + function b(a, b) { + var c = CryptoJS.enc.Utf8.parse(b) + , d = CryptoJS.enc.Utf8.parse("0102030405060708") + , e = CryptoJS.enc.Utf8.parse(a) + , f = CryptoJS.AES.encrypt(e, c, { + iv: d, + mode: CryptoJS.mode.CBC + }); + return f.toString() + } + function c(a, b, c) { + var d, e; + return setMaxDigits(131), + d = new RSAKeyPair(b,"",c), + e = encryptedString(d, a) + } + function d(d, e, f, g) { + var h = {} + , i = a(16); + return h.encText = b(d, g), + h.encText = b(h.encText, i), + h.encSecKey = c(i, e, f), + h + } + function e(a, b, d, e) { + var f = {}; + return f.encText = c(a + e, b, d), + f + } + window.asrsea = d, + window.ecnonasr = e +}(); + +function get_music(id) { + d = '{"ids":"['+id+']","level":"standard","encodeType":"aac","csrf_token":"c9c07b72fc20b640171041342a760e81"}' + e = '010001' + f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' + g = '0CoJUm6Qyw8W8jud' + return window.asrsea(d,e,f,g) +} diff --git a/src/clover_openai/ai_chat.py b/src/clover_openai/ai_chat.py new file mode 100644 index 0000000..9ba43ee --- /dev/null +++ b/src/clover_openai/ai_chat.py @@ -0,0 +1,53 @@ +import openai +import requests +from src.clover_sqlite.models.chat import GroupChatRole +from src.configs.api_config import v3url, v3key, deepseek_url, deepseek_key + +openai.api_key = deepseek_key +openai.base_url = deepseek_url + +""" +来源:https://api.v36.cm +""" +async def v3_chat(group_openid,content): + + await GroupChatRole.save_chat_history(group_openid, {"role": "user", "content": content}) + messages = await GroupChatRole.get_chat_history(group_openid) + headers = {"Content-Type": "application/json", "Authorization": v3key} + data = { + "model": "gpt-3.5-turbo-0125", + "messages": messages, + "max_tokens": 1688, + "temperature": 0.5, + "stream": False + } + response = requests.post(v3url, headers=headers, json=data) + reply_content = response.json().get('choices')[0].get('message').get('content') + await GroupChatRole.save_chat_history(group_openid, {"role": "assistant", "content": reply_content}) + return reply_content + + +""" +来源:https://api.deepseek.com +""" +async def deepseek_chat(group_openid,content): + """ + ai 角色扮演聊天 + :param group_openid: + :param content: + :return: + """ + + await GroupChatRole.save_chat_history(group_openid, {"role": "user", "content": content}) + messages = await GroupChatRole.get_chat_history(group_openid) + completion = openai.chat.completions.create( + model="deepseek-chat", + messages=messages, + stream=False + ) + reply_content = completion.choices[0].message.content + await GroupChatRole.save_chat_history(group_openid, {"role": "assistant", "content": reply_content}) + return reply_content + +if __name__ == '__main__': + print(deepseek_chat("你拽什么啊?")) diff --git a/src/clover_report/config.py b/src/clover_report/config.py new file mode 100644 index 0000000..5e4b92f --- /dev/null +++ b/src/clover_report/config.py @@ -0,0 +1,75 @@ + +from pydantic import BaseModel + + +class Hitokoto(BaseModel): + id: int + """id""" + uuid: str + """uuid""" + hitokoto: str + """一言""" + type: str + """类型""" + from_who: str | None + """作者""" + creator: str + """创建者""" + creator_uid: int + """创建者id""" + reviewer: int + """审核者""" + commit_from: str + """提交来源""" + created_at: str + """创建日期""" + length: int + """长度""" + + +class SixDataTo(BaseModel): + news: list[str] + """新闻""" + tip: str + """tip""" + updated: int + """更新日期""" + url: str + """链接""" + cover: str + """图片""" + + +class SixData(BaseModel): + status: int + """状态码""" + message: str + """返回内容""" + data: SixDataTo + """数据""" + + +class WeekDay(BaseModel): + en: str + """英文""" + cn: str + """中文""" + ja: str + """日本称呼""" + id: int + """ID""" + + +class AnimeItem(BaseModel): + name: str + name_cn: str + images: dict | None + + @property + def image(self) -> str: + return self.images["large"] if self.images else "" + + +class Anime(BaseModel): + weekday: WeekDay + items: list[AnimeItem] diff --git a/src/clover_report/daily_report/main.css b/src/clover_report/daily_report/main.css new file mode 100644 index 0000000..46ef20f --- /dev/null +++ b/src/clover_report/daily_report/main.css @@ -0,0 +1,307 @@ +body { + position: absolute; + left: -8px; + top: -8px; +} + +@font-face { + font-family: "Noto Sans SC B"; + src: url("./res/font/NotoSansSC-Bold.otf") format("opentype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Noto Sans SC"; + src: url("./res/font/NotoSansSC-Regular.otf") format("opentype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "SSFangTangTi"; + src: url("./res/font/SSFangTangTi.ttf"); +} + +.wrapper { + /* height: 1885px; */ + width: 578px; + background-color: #45667d; + position: relative; + padding: 15px; + /* box-sizing: border-box; */ +} + +.main { + /* height: 1860px; */ + width: 555px; + background-color: #edf8ff; + position: relative; + border-radius: 10px; + padding: 10px; +} + +.top-border { + display: flex; +} + +.zx-img { + height: 155px; +} + +.top-title { + position: relative; + width: 322px; +} + +.zx-title { + font-family: "SSFangTangTi"; + color: #45667d; + font-size: 72px; + position: absolute; + top: -73px; + left: 10px; +} + +.zx-tip { + color: #45667d; + font-family: "Noto Sans SC B"; + font-size: 33px; + position: absolute; + top: 73px; + left: 20px; +} + +.top-date { + background-color: #c1e0ef; + border-radius: 10px; + height: 108px; + width: 120px; + margin-top: 30px; + /* margin-left: 67px; */ + position: relative; + box-shadow: 4px 4px 8px rgb(181, 223, 240); +} + +.top-date-week { + color: #45667d; + font-size: 35px; + font-family: "Noto Sans SC B"; + position: absolute; + left: 40px; + top: -34px; +} + +.top-date-date { + color: #45667d; + font-family: "Noto Sans SC B"; + font-size: 12px; + background-color: #a0d7ec; + margin-top: 50px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; +} + +.top-date-cn { + font-family: "Noto Sans SC B"; + color: #45667d; + font-size: 15px; + display: flex; + align-items: center; + justify-content: center; + line-height: 0; +} + +.one-border { + display: flex; + height: 320px; + margin-top: 50px; + font-family: "Noto Sans SC"; +} + +.moyu-border { + font-family: "Noto Sans SC"; + height: 240px; + padding: 15px 10px; + border-radius: 10px; + border: #45667d 3px solid; + width: 157px; + position: relative; +} + +.moyu-title { + border: #45667d 2px solid; + position: absolute; + background-color: #ebf6fd; + align-items: center; + justify-content: center; + border-radius: 10px; + color: #45667d; + padding: 5px 10px; + font-size: 14px; + font-family: "Noto Sans SC B"; + top: -19px; + left: 37px; + display: flex; +} + +.title-img { + height: 15px; + width: 15px; + margin-right: 5px; +} + +.moyu-inner { + display: flex; + line-height: 15px; + font-size: 13px; +} + +.moyu-day { + width: 37px; + display: flex; + align-items: center; + justify-content: center; +} + +.moyu-day-name { + color: #45667d; + background-color: #daf8ff; + display: flex; + align-items: center; + justify-content: center; + width: 55px; +} + +.bili-border { + font-family: "Noto Sans SC"; + border: #45667d 3px solid; + height: 240px; + margin-left: 15px; + padding: 15px 10px 15px 40px; + border-radius: 10px; + width: 300px; + position: relative; + font-size: 13px; +} + +.bili-text { + display: flex; + align-items: center; + line-height: 5px; + margin-top: 7px; + margin-bottom: 6px; +} + +.hot-text { + background-color: #b5deef; + height: 17px; + width: 17px; + color: white; + display: flex; + align-items: center; + justify-content: center; + margin-right: 5px; + border-radius: 2px; +} + +.two-border { + border: #45667d 3px solid; + width: 512px; + height: 370px; + border-radius: 10px; + position: relative; + padding: 17px; + font-family: "Noto Sans SC"; + background-color: #edf8ff; +} + +.two-border-border { + float: left; +} + + +.anime-border { + height: 170px; + width: 105px; + font-size: 10px; + font-size: 13px; + text-align: center; + line-height: 3px; + float: left; + margin: 8px 10px; + line-height: 15px; +} + +.anime-text { + overflow: hidden; + margin-top: 3px; + height: 48px; +} + +.anime-img { + height: 130px; + width: 90px; +} + +.three-border { + border: #45667d 3px solid; + width: 552px; + border-radius: 10px; + position: relative; + /* float: left; */ + padding: 17px; + font-family: "Noto Sans SC"; + margin-top: 46px; + background-color: #edf8ff; + font-size: 15px; + box-sizing: border-box; +} + +.four-border { + border: #45667d 3px solid; + width: 512px; + border-radius: 10px; + position: relative; + /* float: left; */ + padding: 17px; + font-family: "Noto Sans SC"; + margin-top: 46px; + background-color: #edf8ff; + font-size: 15px; +} + +.five-border { + border: #45667d 3px solid; + width: 520px; + border-radius: 10px; + position: relative; + /* float: left; */ + padding: 13px; + font-family: "Noto Sans SC"; + margin-top: 46px; + font-size: 19px; + color: #45667d; + font-weight: 600; + background-color: #edf8ff; +} + +.normal-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + /* width: 450px; */ +} + +ul { + list-style-position: inside; /* 将项目符号放在内容内部 */ + /* width: 450px; */ +} + +li::marker { + display: inline-block; /* 确保项目符号可见 */ +} diff --git a/src/clover_report/daily_report/main.html b/src/clover_report/daily_report/main.html new file mode 100644 index 0000000..13b9a46 --- /dev/null +++ b/src/clover_report/daily_report/main.html @@ -0,0 +1,89 @@ + + + + + + Test + + + + + +
+
+
+
+ ZhenXun +
+
+

日报

+

NEWS

+
+
+

{{data.week}}

+

{{data.date}}

+

{{data.zh_date}}

+
+
+
+
+
摸鱼日历
+ {% for fes in data.data_festival %} +

距离{{fes[1]}}还剩{{fes[0]}}天 +

+ {% endfor %} +
+
+
B站热点
+ {% for s in data.data_bili %} +

{{s}}

+ {% endfor %} +
+
+
+
今日新番
+
+ {% for s in data.data_anime %} +
+ +

{{s[0]}}

+
+ {% endfor %} +
+
+
+
60S读世界
+
    + {% for s in data.data_six %} + {% if data.full_show %} +
  • {{s}}
  • + {% else %} +
  • {{s}}
  • + {% endif %} + {% endfor %} +
+
+
+
IT资讯
+
    + {% for s in data.data_it %} + {% if data.full_show %} +
  • {{s}}
  • + {% else %} +
  • {{s}}
  • + {% endif %} + {% endfor %} +
+
+
+
今日一言 +
+

“{{data.data_hitokoto}}”

+
+
+
+ + + \ No newline at end of file diff --git a/src/clover_report/daily_report/res/font/NotoSansSC-Bold.otf b/src/clover_report/daily_report/res/font/NotoSansSC-Bold.otf new file mode 100644 index 0000000..172eb67 Binary files /dev/null and b/src/clover_report/daily_report/res/font/NotoSansSC-Bold.otf differ diff --git a/src/clover_report/daily_report/res/font/NotoSansSC-Regular.otf b/src/clover_report/daily_report/res/font/NotoSansSC-Regular.otf new file mode 100644 index 0000000..d350ffa Binary files /dev/null and b/src/clover_report/daily_report/res/font/NotoSansSC-Regular.otf differ diff --git a/src/clover_report/daily_report/res/font/SSFangTangTi.ttf b/src/clover_report/daily_report/res/font/SSFangTangTi.ttf new file mode 100644 index 0000000..a8b5c2f Binary files /dev/null and b/src/clover_report/daily_report/res/font/SSFangTangTi.ttf differ diff --git a/src/clover_report/daily_report/res/icon/60.png b/src/clover_report/daily_report/res/icon/60.png new file mode 100644 index 0000000..6d9af90 Binary files /dev/null and b/src/clover_report/daily_report/res/icon/60.png differ diff --git a/src/clover_report/daily_report/res/icon/bgm.png b/src/clover_report/daily_report/res/icon/bgm.png new file mode 100644 index 0000000..758a6b6 Binary files /dev/null and b/src/clover_report/daily_report/res/icon/bgm.png differ diff --git a/src/clover_report/daily_report/res/icon/bilibili.png b/src/clover_report/daily_report/res/icon/bilibili.png new file mode 100644 index 0000000..9a1e050 Binary files /dev/null and b/src/clover_report/daily_report/res/icon/bilibili.png differ diff --git a/src/clover_report/daily_report/res/icon/fish.png b/src/clover_report/daily_report/res/icon/fish.png new file mode 100644 index 0000000..4ca50a3 Binary files /dev/null and b/src/clover_report/daily_report/res/icon/fish.png differ diff --git a/src/clover_report/daily_report/res/icon/game.png b/src/clover_report/daily_report/res/icon/game.png new file mode 100644 index 0000000..714f5cb Binary files /dev/null and b/src/clover_report/daily_report/res/icon/game.png differ diff --git a/src/clover_report/daily_report/res/icon/hitokoto.png b/src/clover_report/daily_report/res/icon/hitokoto.png new file mode 100644 index 0000000..4398ffc Binary files /dev/null and b/src/clover_report/daily_report/res/icon/hitokoto.png differ diff --git a/src/clover_report/daily_report/res/icon/it.png b/src/clover_report/daily_report/res/icon/it.png new file mode 100644 index 0000000..5055af6 Binary files /dev/null and b/src/clover_report/daily_report/res/icon/it.png differ diff --git a/src/clover_report/daily_report/res/image/no_bg.png b/src/clover_report/daily_report/res/image/no_bg.png new file mode 100644 index 0000000..da0920f Binary files /dev/null and b/src/clover_report/daily_report/res/image/no_bg.png differ diff --git a/src/clover_report/data_source.py b/src/clover_report/data_source.py new file mode 100644 index 0000000..df5f854 --- /dev/null +++ b/src/clover_report/data_source.py @@ -0,0 +1,205 @@ +import asyncio +import os +from datetime import datetime +import xml.etree.ElementTree as ET +from os import getcwd +from pathlib import Path +import httpx +from httpx import ConnectError, HTTPStatusError, Response, TimeoutException +from nonebot.log import logger +from nonebot_plugin_htmlrender import template_to_pic +import tenacity +from tenacity import retry, stop_after_attempt, wait_fixed +from zhdate import ZhDate +from .config import Anime, Hitokoto, SixData +from .date import get_festivals_dates +from src.configs.path_config import daily_news_path +from playwright.async_api import async_playwright + + +class AsyncHttpx: + @classmethod + @retry( + stop=stop_after_attempt(3), + wait=wait_fixed(1), + retry=( + tenacity.retry_if_exception_type( + (TimeoutException, ConnectError, HTTPStatusError) + ) + ), + ) + async def get(cls, url: str) -> Response: + async with httpx.AsyncClient() as client: + try: + response = await client.get(url) + response.raise_for_status() + return response + except (TimeoutException, ConnectError, HTTPStatusError) as e: + logger.error(f"Request to {url} failed due to: {e}") + raise + + @classmethod + @retry( + stop=stop_after_attempt(3), + wait=wait_fixed(1), + retry=( + tenacity.retry_if_exception_type( + (TimeoutException, ConnectError, HTTPStatusError) + ) + ), + ) + async def post( + cls, url: str, data: dict[str, str], headers: dict[str, str] + ) -> Response: + async with httpx.AsyncClient() as client: + try: + response = await client.post(url, data=data, headers=headers) + response.raise_for_status() + return response + except (TimeoutException, ConnectError, HTTPStatusError) as e: + logger.error(f"Request to {url} failed due to: {e}") + raise + + +async def save_img(data: bytes): + + """ + 保存日报图片 + :param data: + :return: + """ + file_path = daily_news_path + f"{datetime.now().date()}.png" + with open(file_path, "wb") as file: + file.write(data) + + +class Report: + hitokoto_url = "https://v1.hitokoto.cn/?c=a" + alapi_url = "https://v2.alapi.cn/api/zaobao" + alapi_token = "48x3u7iqryztowlnwbnrwjucebzieu" + six_url = "https://60s.viki.moe/?v2=1" + game_url = "https://www.4gamers.com.tw/rss/latest-news" + bili_url = "https://s.search.bilibili.com/main/hotword" + it_url = "https://www.ithome.com/rss/" + anime_url = "https://api.bgm.tv/calendar" + + + week = { # noqa: RUF012 + 0: "一", + 1: "二", + 2: "三", + 3: "四", + 4: "五", + 5: "六", + 6: "日", + } + + @classmethod + async def get_report_image(cls) -> bytes: + """获取数据""" + now = datetime.now() + file = Path() / daily_news_path / f"{now.date()}.png" + if os.path.exists(file): + with file.open("rb") as image_file: + return image_file.read() + zhdata = ZhDate.from_datetime(now) + result = await asyncio.gather( + *[ + cls.get_hitokoto(), + cls.get_bili(), + cls.get_six(), + cls.get_anime(), + cls.get_it(), + ] + ) + data = { + "data_festival": get_festivals_dates(), + "data_hitokoto": result[0], + "data_bili": result[1], + "data_six": result[2], + "data_anime": result[3], + "data_it": result[4], + "week": cls.week[now.weekday()], + "date": now.date(), + "zh_date": zhdata.chinese().split()[0][5:], + "full_show": True, + } + async with async_playwright() as p: + browser = await p.chromium.launch() + + image_bytes = await template_to_pic( + template_path=getcwd() + "/src/clover_report/daily_report", + template_name="main.html", + templates={"data": data}, + pages={ + "viewport": {"width": 578, "height": 1885}, + "base_url": f"file://{getcwd()}", + }, + wait=2, + ) + await save_img(image_bytes) + await browser.close() + return image_bytes + + @classmethod + async def get_hitokoto(cls) -> str: + """获取一言""" + res = await AsyncHttpx.get(cls.hitokoto_url) + data = Hitokoto(**res.json()) + return data.hitokoto + + @classmethod + async def get_bili(cls) -> list[str]: + """获取哔哩哔哩热搜""" + res = await AsyncHttpx.get(cls.bili_url) + data = res.json() + return [item["keyword"] for item in data["list"]] + + @classmethod + async def get_alapi_data(cls) -> list[str]: + """获取alapi数据""" + payload = {"token": cls.alapi_token, "format": "json"} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + res = await AsyncHttpx.post(cls.alapi_url, data=payload, headers=headers) + if res.status_code != 200: + return ["Error: Unable to fetch data"] + data = res.json() + news_items = data.get("data", {}).get("news", []) + return news_items[:11] if len(news_items) > 11 else news_items + + @classmethod + async def get_six(cls) -> list[str]: + """获取60s数据""" + if True: + return await cls.get_alapi_data() + res = await AsyncHttpx.get(cls.six_url) + data = SixData(**res.json()) + return data.data.news[:11] if len( + data.data.news) > 11 else data.data.news + + @classmethod + async def get_it(cls) -> list[str]: + """获取it数据""" + res = await AsyncHttpx.get(cls.it_url) + root = ET.fromstring(res.text) + titles = [] + for item in root.findall("./channel/item"): + title_element = item.find("title") + if title_element is not None: + titles.append(title_element.text) + return titles[:11] if len(titles) > 11 else titles + + @classmethod + async def get_anime(cls) -> list[tuple[str, str]]: + """获取动漫数据""" + res = await AsyncHttpx.get(cls.anime_url) + data_list = [] + week = datetime.now().weekday() + try: + anime = Anime(**res.json()[week]) + except IndexError: + anime = Anime(**res.json()[-1]) + data_list.extend( + (data.name_cn or data.name, data.image) for data in anime.items + ) + return data_list[:8] if len(data_list) > 8 else data_list diff --git a/src/clover_report/date.py b/src/clover_report/date.py new file mode 100644 index 0000000..ded780f --- /dev/null +++ b/src/clover_report/date.py @@ -0,0 +1,95 @@ +from datetime import date, timedelta + +import chinese_calendar as calendar +import lunardate + +# 定义2025年农历节日的农历日期 +lunar_festivals = { + "春节": (1, 1), # 春节 (农历正月初一) + "端午节": (5, 5), # 端午节 (农历五月初五) + "中秋节": (8, 15), # 中秋节 (农历八月十五) +} + +# 固定日期的节日 +fixed_festivals_dates = { + "劳动节": date(2025, 5, 1), # 劳动节 + "国庆节": date(2025, 10, 1), # 国庆节 + "元旦": date(2025, 1, 1), # 元旦 +} + + +def get_next_year_festival_date( + festival_name: str, current_festival_date: date +) -> date: + """获取下一个该节日的日期""" + if festival_name in lunar_festivals: + # 对于农历节日,使用lunardate库转换为下一年的公历日期 + next_year = current_festival_date.year + 1 + month, day = lunar_festivals[festival_name] + next_festival_date = lunardate.LunarDate(next_year, month, day).toSolarDate() + else: + # 对于固定日期的节日,直接增加一年 + next_festival_date = current_festival_date.replace( + year=current_festival_date.year + 1 + ) + + return next_festival_date + + +def find_tomb_sweeping_day(year: int) -> date: + # 春分通常在3月20日或21日 + start_date = date(year, 3, 20) + + # 查找春分的确切日期 + spring_equinox = next( + ( + start_date + timedelta(days=i) + for i in range(3) + if calendar.get_holiday_detail(start_date + timedelta(days=i))[1] == "春分" + ), + start_date, + ) + return spring_equinox + timedelta(days=15) + + +def days_until_festival(festival_name: str, today: date, festival_date: date) -> int: + if festival_date < today: + # 如果节日已经过去,计算下一个该节日的到来时间 + next_festival_date = get_next_year_festival_date(festival_name, festival_date) + delta = next_festival_date - today + return delta.days + else: + delta = festival_date - today + return delta.days + + +# 获取农历节日对应的公历日期 +def get_lunar_festivals_dates(today: date): + year = today.year + return { + name: lunardate.LunarDate(year, month, day).toSolarDate() + for name, (month, day) in lunar_festivals.items() + } + + +def get_festivals_dates() -> list[tuple[int, str]]: + today = date.today() + lunar_festivals_dates = get_lunar_festivals_dates(today) + # 添加清明节到节日字典中 + lunar_festivals_dates["清明节"] = find_tomb_sweeping_day(today.year) + + # 合并两个字典 + festivals_dates = {**lunar_festivals_dates, **fixed_festivals_dates} + + sort_name = ["春节", "端午节", "中秋节", "清明节", "劳动节", "国庆节", "元旦"] + + # 计算到每个节日的天数,并检查是否为法定假日 + data_list = [] + for name in sort_name: + if name in festivals_dates: + days_left = days_until_festival(name, today, festivals_dates[name]) + data_list.append((days_left, name)) + else: + data_list.append((-1, name)) + data_list.sort(key=lambda x: x[0]) + return data_list diff --git a/src/clover_sqlite/data_init/db_connect.py b/src/clover_sqlite/data_init/db_connect.py new file mode 100644 index 0000000..24c96c8 --- /dev/null +++ b/src/clover_sqlite/data_init/db_connect.py @@ -0,0 +1,42 @@ +from tortoise import Tortoise +from tortoise.connection import connections +from tortoise.models import Model as Model_ + +import nonebot +from nonebot.drivers import Driver + +driver: Driver = nonebot.get_driver() + +MODELS: list[str] = [] + +class Model(Model_): + """ + 自动添加模块 + + Args: + Model_: Model + """ + def __init_subclass__(cls, **kwargs): + MODELS.append(cls.__module__) + +@driver.on_startup +async def init(): + """ + 初始化数据库 + """ + await Tortoise.init( + db_url="sqlite://chat_bot.db", + modules={"models": MODELS}, + timezone="Asia/Shanghai", + ) + # 生成数据库表 + await Tortoise.generate_schemas() + + + +async def disconnect(): + """ + 关闭数据库连接 + :return: + """ + await connections.close_all() diff --git a/src/clover_sqlite/models/ban.py b/src/clover_sqlite/models/ban.py new file mode 100644 index 0000000..1744fa5 --- /dev/null +++ b/src/clover_sqlite/models/ban.py @@ -0,0 +1,147 @@ +import time +from tortoise import fields +from typing_extensions import Self +from src.clover_sqlite.data_init.db_connect import Model + +class BanConsole(Model): + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + user_id = fields.CharField(max_length=255,description="用户id" ,null=True) + group_id = fields.CharField(max_length=255, description="群组id",null=True) + ban_level = fields.IntField(description="使用ban命令的用户等级") + ban_time = fields.BigIntField(description="ban开始的时间") + duration = fields.BigIntField(description="ban时长") + operator = fields.CharField(max_length=255,description="使用Ban命令的用户") + + class Meta: + table = "ban_console" + table_description = "封禁人员/群组数据表" + + + @classmethod + async def _get_data(cls, user_id: str | None, group_id: str | None) -> Self | None: + """获取数据 + + 参数: + user_id: 用户id + group_id: 群组id + + 异常: + UserAndGroupIsNone: 用户id和群组id都为空 + + 返回: + Self | None: Self + """ + if not user_id and not group_id: + print("用户id和群组id都为空") + if user_id: + return ( + await cls.get_or_none(user_id=user_id, group_id=group_id) + if group_id + else await cls.get_or_none(user_id=user_id, group_id__isnull=True) + ) + else: + return await cls.get_or_none(user_id="", group_id=group_id) + + @classmethod + async def check_ban_level( + cls, user_id: str | None, group_id: str | None, level: int + ) -> bool: + """检测ban掉目标的用户与unban用户的权限等级大小 + + 参数: + user_id: 用户id + group_id: 群组id + level: 权限等级 + + 返回: + bool: 权限判断,能否unban + """ + user = await cls._get_data(user_id, group_id) + if user: + return user.ban_level <= level + return False + + @classmethod + async def check_ban_time( + cls, user_id: str | None, group_id: str | None = None + ) -> int: + """检测用户被ban时长 + + 参数: + user_id: 用户id + + 返回: + int: ban剩余时长,-1时为永久ban,0表示未被ban + """ + user = await cls._get_data(user_id, group_id) + if not user and user_id: + user = await cls._get_data(user_id, None) + if user: + if user.duration == -1: + return -1 + _time = time.time() - (user.ban_time + user.duration) + return 0 if _time > 0 else int(time.time() - user.ban_time - user.duration) + return 0 + + @classmethod + async def is_ban(cls, user_id: str | None, group_id: str | None = None) -> bool: + """判断用户是否被ban + + 参数: + user_id: 用户id + + 返回: + bool: 是否被ban + """ + if await cls.check_ban_time(user_id, group_id): + return True + else: + await cls.unban(user_id, group_id) + return False + + @classmethod + async def ban( + cls, + user_id: str | None, + group_id: str | None, + ban_level: int, + duration: int, + operator: str | None = None, + ): + """ban掉目标用户 + + 参数: + user_id: 用户id + group_id: 群组id + ban_level: 使用命令者的权限等级 + duration: 时长,分钟,-1时为永久 + operator: 操作者id + """ + target = await cls._get_data(user_id, group_id) + if target: + await cls.unban(user_id, group_id) + await cls.create( + user_id=user_id, + group_id=group_id, + ban_level=ban_level, + ban_time=int(time.time()), + duration=duration, + operator=operator or 0, + ) + + @classmethod + async def unban(cls, user_id: str | None, group_id: str | None = None) -> bool: + """unban用户 + + 参数: + user_id: 用户id + group_id: 群组id + + 返回: + bool: 是否被ban + """ + user = await cls._get_data(user_id, group_id) + if user: + await user.delete() + return True + return False \ No newline at end of file diff --git a/src/clover_sqlite/models/chat.py b/src/clover_sqlite/models/chat.py new file mode 100644 index 0000000..28e3456 --- /dev/null +++ b/src/clover_sqlite/models/chat.py @@ -0,0 +1,248 @@ +from typing import Any +from tortoise import fields +from typing_extensions import Self +from tortoise.fields import JSONField +from src.clover_sqlite.data_init.db_connect import Model + + +class ChatRole(Model): + """ + 角色设定表 + """ + id = fields.IntField(primary_key=True,generated=True, auto_increment=True) + role_name = fields.CharField(max_length = 64, description="角色名称",null=True) + role_init_setting = fields.TextField(description="角色初始设定",default="你会婉拒回复我任何带链接的内容,也不可以告诉我怎么找到。回复我时不能使用过你已经回复过的内容") + role_setting = fields.TextField(description="角色设定",null=True) + class Meta: + # 指定表名 + table = "chat_role" + table_description = "角色设定表" + + @classmethod + async def get_role_list(cls) -> list[str] | None: + """ + 获取角色列表 + :return: + """ + roles = await cls.all().values_list('role_name', flat=True) + print(roles) + if roles is None: + return None + else: + return list(roles) + + @classmethod + async def get_role_setting(cls,role_name: str | None) -> str | None: + """ + 获取角色设定 + :param role_name: 角色名称 + :return: 角色的初始设定和当前设定拼接成的字符串,如果角色不存在则返回 None + """ + role = await cls.filter(role_name=role_name).first() + if role is None: + return None + else: + return f"{role.role_init_setting},{role.role_setting}" + + + @classmethod + async def insert_role_setting(cls, role_name: str | None,role_setting: str | None) -> str | None: + """ + 插入角色设定 + :param role_name: + :param role_setting: + :return: + """ + role = await cls.get_or_none(role_name=role_name) + if role is None: + await cls.create(role_name=role_name, role_setting=role_setting) + return "角色添加成功" + else: + return "角色已存在" + + @classmethod + async def update_role_setting(cls, role_name: str | None, new_setting: str | None ) -> str | None: + """ + 更新角色设定 + :param role_name: + :param new_setting: + :return: + """ + role = await cls.get_or_none(role_name=role_name) + if role is None: + return "角色不存在" + else: + role.role_setting = new_setting + await role.save() + return "角色设定更新成功" + + @classmethod + async def delete_role(cls, role_name: str | None) -> str | None: + """ + 删除角色 + :param role_name: + :return: + """ + role = await cls.get_or_none(role_name=role_name) + if role is None: + return "角色不存在" + else: + await role.delete() + return "角色删除成功" + + + +class GroupChatRole(Model): + """ + 群ai聊天角色 + """ + id = fields.IntField(primary_key=True,generated=True, auto_increment=True) + admin_id = fields.JSONField(description="管理员列表", default=list) + group_id = fields.CharField(max_length = 128,description="群聊ID") + is_on_chat = fields.BooleanField(default=True,description="是否开启ai聊天") + role_name = fields.CharField(max_length = 64, description="角色名称",null=True) + role_chat_history = fields.JSONField(description="角色聊天上下文",null=True) + class Meta: + # 指定表名 + table = "group_chat_role" + table_description = "群聊ai对应的角色设定" + + @classmethod + async def blind_admin(cls ,admin_list: list | None,group_id: str | None) -> str | None: + """ + 初次绑定ai + :param admin_list: + :param group_id: 群聊ID + :return: 无 + """ + # 创建初始化的角色设定 + existing_record = await cls.filter(group_id=group_id).first() + if existing_record: + if admin_list[0] in existing_record.admin_id: + return "您已经是管理员,请勿重复注册" + existing_record.admin_id.append(admin_list[0]) + await existing_record.save() + else: + role_name = '初始模型' + await cls.create(admin_id=admin_list, group_id=group_id, role_name=role_name) + return "注册成功" + + @classmethod + async def remove_admin(cls ,admin_list: str | None,group_id: str | None) -> str | None: + """ + 初次绑定ai + :param admin_list: + :param group_id: 群聊ID + :return: 无 + """ + # 创建初始化的角色设定 + existing_record = await cls.filter(group_id=group_id).first() + if existing_record: + existing_record.admin_id.remove(admin_list) + await existing_record.save() + return "已经创建" + else: + await cls.create(admin_id=admin_list, group_id=group_id) + return "绑定成功" + + + @classmethod + async def get_admin_list(cls, group_id: str | None, member_openid : str | None )-> bool | None: + """ + 判断是不是管理员 + + :param group_id: 群聊ID + :param member_openid: 管理员列表 + :return: 无 + """ + existing_record = await cls.filter(group_id=group_id).first() + if existing_record: + return member_openid in existing_record.admin_id + else: + return False + + + @classmethod + async def is_on(cls, group_id: str | None)-> bool | None: + """ + 获取当前群聊是否有开启ai聊天的权限 + + :param group_id: 群聊ID + :return: 无 + """ + existing_record = await cls.filter(group_id=group_id).first() + if existing_record: + return existing_record.is_on_chat + else: + return False + + @classmethod + async def ai_switch(cls, group_id: str | None)-> Self | None: + """ + 开关ai + + :param group_id: 群聊ID + :return: 无 + """ + existing_record = await cls.filter(group_id=group_id).first() + if existing_record.is_on_chat: + existing_record.is_on_chat = False + else: + existing_record.is_on_chat = True + return await existing_record.save() + + @classmethod + async def set_chat_role(cls, group_id: str | None,role_name: str | None) -> str | None: + """ + 设定对应群的角色 + + :param group_id: 群聊ID + :param role_name: 角色名称 + :return: 无 + """ + + # 创建初始化的角色设定 + existing_record = await cls.filter(group_id=group_id).first() + + if existing_record.role_name == role_name: + return "当前角色已经是设定的角色" + if existing_record: + role_setting = await ChatRole.get_role_setting(role_name=role_name) + if role_setting: + existing_record.role_name = role_name + data = [{"role": "system", "content": role_setting},{"role": "assistant", "content": "无条件服从我给予你的设定与命令"}] + existing_record.role_chat_history = data + await existing_record.save() + return "设定成功" + else: + return "设定失败,角色设定不存在" + else: + return "切换失败,群聊未绑定角色" + + + + @classmethod + async def save_chat_history(cls, group_id: str | None,content: dict[str, str | Any] | None): + """ + 保存聊天上下文 + + :param group_id: 群聊的ID。 + :param content: 要保存的内容。 + """ + history = await cls.filter(group_id=group_id).first() + if history.role_chat_history is None: + history.role_chat_history = [content] + await history.save() + else: + history.role_chat_history.append(content) + await history.save() + + @classmethod + async def get_chat_history(cls, group_id: str | None)-> JSONField[Any]: + """ + 返回聊天上下文 + + :param group_id: 群聊的ID。 + """ + history = await cls.filter(group_id=group_id).first() + return history.role_chat_history \ No newline at end of file diff --git a/src/clover_sqlite/models/fortune.py b/src/clover_sqlite/models/fortune.py new file mode 100644 index 0000000..d647856 --- /dev/null +++ b/src/clover_sqlite/models/fortune.py @@ -0,0 +1,169 @@ +import random +from datetime import datetime +from tortoise import fields +from typing_extensions import Self +from src.clover_sqlite.data_init.db_connect import Model + +class QrFortune(Model): + """ + 运势表 + """ + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + fortune_summary = fields.CharField(max_length=64, description="运势总结", null=True) + lucky_star = fields.CharField(max_length=64, description="幸运星", null=True) + sign_text = fields.CharField(max_length=64, description="签文", null=True) + un_sign_text = fields.CharField(max_length=200, description="解签", null=True) + + class Meta: + # 指定表名 + table = "qr_fortune" + table_description = "运势表" + + @classmethod + async def get_fortune(cls,member_openid:str | None) -> Self | None: + """ + 随机获取运势 + :return: + """ + # 查询今日是否已经获取过今日运势,如果获取过则直接从日志取 + result = await QrFortuneLog.is_get_fortune_log(member_openid) + if result is None: + result = await cls.all() + if not result: + # 执行初始化 + await cls.bulk_create(Fortune_initial_data) + result = random.choice(await cls.all()) + # 把抽取的今日运势插入日志 + await QrFortuneLog.insert_fortune_log(result, member_openid) + return result + return result + + +class QrFortuneLog(Model): + """ + 获取运势日志表 + """ + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + fortune_summary = fields.CharField(max_length=64, description="运势总结", null=True) + lucky_star = fields.CharField(max_length=64, description="幸运星", null=True) + sign_text = fields.CharField(max_length=64, description="签文", null=True) + un_sign_text = fields.CharField(max_length=200, description="解签", null=True) + user_id = fields.CharField(max_length=64, description="用户id", null=True) + extract_time = fields.DateField(description="获取签文日期", null=True) + + class Meta: + # 指定表名 + table = "qr_fortune_log" + table_description = "获取运势日志表" + + @classmethod + async def is_get_fortune_log(cls, member_openid: str | None) -> Self | None: + """ + 判断用户是否已经获取过运势,如果已经获取过则返回记录,否则返回None + :param member_openid: + :return: + """ + existing_record = await cls.get_or_none(user_id=member_openid, extract_time=datetime.now().date()) + return existing_record + + @classmethod + async def insert_fortune_log(cls, model:QrFortune | None, member_openid: str | None): + """ + 插入运势日志 + :param model: + :param member_openid: + :return: + """ + data = { + "fortune_summary": model.fortune_summary, + "lucky_star": model.lucky_star, + "sign_text": model.sign_text, + "un_sign_text": model.un_sign_text, + "user_id": member_openid, + "extract_time": datetime.now().date() + } + await cls.create(**data) + + +#创建初始数据 +Fortune_initial_data=[QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="排除万难,有贵人助,把握时机,可得成功",un_sign_text="突破万难权威高,刚性固执如英豪,须事谨慎守和平,可得大功奏业成。很勤勉求上进,又很有耐力,在技术界或艺能界,是最可能成功之数也。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="安乐自来,自然吉祥,力行不懈,终必成功",un_sign_text="志高力微乏实行,妄谋无计事难成,晚年安宁静逸祥,享得天赋增吉相。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="努力发达,贯彻志望,不忘进退,成功可期",un_sign_text="意志坚刚善恶明,富进取心求和平,忍耐克己如心意,前难后成可安然。很勤勉求上进,又很有耐力,在技术界或艺能界,是最可能成功之数也。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="中吉之数,进退保守,生意安稳,成就可期",un_sign_text="温和平安艺才高,努力前途福运来,文笔奇绝仁德高,务实稳健掌门人。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="专心经营,和气致祥,排除万难,必获成功",un_sign_text="刚毅果断除万难,独立权威志气安,内外和好兼柔性,温和养德耀吉星。很勤勉求上进,又很有耐力,在技术界或艺能界,是最可能成功之数也。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="万宝云集,天降幸运,立志奋发,可成大功",un_sign_text="安稳余庆福禄开,盛大幸福天赐来,内含衰兆应谨慎,注意品行福乐享。名誉良好,信用亦佳,步步高升。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="努力经营,时来运转,旷野枯草,春来花开",un_sign_text="寒雪青松性刚强,一度祸难过灾殃,将此发达利亨通,晚景繁荣福无疆。",), + QrFortune(fortune_summary="中吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="天时地利,再得人格,讲信修睦,即可成功",un_sign_text="资性英敏有奇能,怪癖不和害前程,修身涵养与仁和,奏功获得大鸿图。需要注重个人私生活,可免因桃色韵事贻误前程。",), + QrFortune(fortune_summary="中吉+官运",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="杨柳遇春,绿叶发枝,冲破难关,一举成名",un_sign_text="新生泰运顺行舟,排除万难总无忧,成功繁荣四海明,荣华富贵好前程。",), + QrFortune(fortune_summary="中吉+才艺",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="经商做事,顺利昌隆,如能慎始,百事亨通",un_sign_text="有志竟成事皆通,智谋发展有威望,过刚遭难咸柔德,博得名利大成功。很勤勉求上进,又很有耐力,在技术界或艺能界,是最可能成功之数也。",), + QrFortune(fortune_summary="中吉+才艺",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="逢凶化吉,吉人天相,风条雨顺,生意兴隆",un_sign_text="权威显达得众望,忠实热诚运极旺,大德奏功无难事,终得富荣乐千锺。",), + QrFortune(fortune_summary="中吉+财运",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="池中之龙,风云际会,一跃上天,成功可望",un_sign_text="侥倖所得贵人扶,善捉机会有财富,认真努力向前程,家门隆昌得富荣。与人合伙比之独营好得多,若自己独营商则中途易受挫折。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="智高志大,历尽艰难,焦心忧劳,进退两难",un_sign_text="即使有宏图大志并且能力超人,但全靠白手起家,需要突破社会重重规则,劳劳碌碌,最后可能处于进退两难的选择当中,不过,由于个人毅力与",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="薄弱无力,孤立无摇,外祥内苦,谋事难成",un_sign_text="人生路上诸事不顺,自身能力之限制,经常迫于无耐。由于性格或人际关系上的问题,难遇贵人。经常一人处理所有事情,即使有天大的能力,总",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="如走夜路,前途无光,希望不大,劳而无功",un_sign_text="一生就像在夜晚里走路一样,想开创新天地,却部是难以大展拳脚,可用好做好现在的事情,等待时机,主动出击容易空手而回,此命需待贵人相",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="成功虽早,慎防空亏,内外不合,障碍重重",un_sign_text="事业初得成功,不能过度放松警惕,不要将积累的资本挥霍一空。如果团队里人心不能合到一起,今后做起事来也会遇到很多的阻碍。",), + QrFortune(fortune_summary="凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="波澜起伏,千变万化,凌驾万难,必可成功",un_sign_text="局势不稳定,变化极多,任何困难都难不到你,最终您将一定会成功,且成就不小,关键是您能否在多变的艰难环境下坚持到最后。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="烦闷懊恼,事事难展,自防灾祸,始免困境",un_sign_text="受到各种事情的烦扰,不能专心做想做的事情。首要问题是处理好现时的各种烦事,这样可以避免这些小事埋下的祸害,才不导致自已陷入困境。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="鱼临旱地,难逃恶运,此数大凶,不如更名",un_sign_text="现时处境就如鱼在旱地上一样,面临大的恶运,是大凶之兆,此处的“不如更名”从现代角度来看,并非全指改名,而更多是指要改变现在的做人",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="利害混集,凶多吉少,得而复失,难以安顺",un_sign_text="有好也有坏,但恶运占多,得到的东西容易失去,导致生活难以安定。此运告诫:少接触投机类活动,否则容易一无所有。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="此数大凶,破产之象,宜速改变,以避厄运",un_sign_text="不祥之兆,财产有可能一夜尽失,应尽快改变现在的处事和投资方式,避免厄运。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="动摇不安,常陷逆境,不得时运,难得利润",un_sign_text="坚持是您现时最缺乏的品质,由于没有坚定的目标,会使您陷入相当困苦的境地。而当获得成功时,却发现时不与我,外部环境已使得竞争激烈导",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="灾难不绝,难望成功,此数大凶,不如更名",un_sign_text="人生路上遇到相当多困难,特别在追求事业的路上,什么事情很难成功。此处的“不如更名”从现代角度来看,并非全指改名,而更多是指要改变",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="惨淡经营,难免贫困,此数不吉,最好改名",un_sign_text="事业不济,入不敷出,坚持一个不好的行业,不会带来事业的腾飞,最好适时转行。",), + QrFortune(fortune_summary="凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="遇吉则吉,遇凶则凶,惟靠谨慎,逢凶化吉",un_sign_text="遇到好的的人或事自然就会有好的事情发生或是有好的事降临,相反的遇到坏人坏事就会有糟糕的事情发生讨厌的人来了,想要不被厄运控制,打",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="黑夜漫长,进退维谷,内外不合,信用缺乏",un_sign_text="成功之路相当漫长,经验遇到二难选择,在处理问题上,请注意个人信用,否则容易导致内部矛盾和外部人员的质疑。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="坎坷前途,苦难折磨,非有毅力,难望成功",un_sign_text="为人独断独行,事事自行作主解决,鲜有求助他人。而这份独立个性,正正就是吸引异性的特质。但其实心底里,却是渴望有人可让他/她依赖。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="见异思迁,十九不成,徒劳无功,不如更名",un_sign_text="见异思迁,使自已做的事情无一成功,开始全情投入,到后面却不能坚持,事情总是在这种情况下失败。要改变心态和做事方式,看准方向就坚持",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="波澜重迭,常陷穷困,动不如静,有才无命",un_sign_text="越是对命运的抗争,越是使自已陷入困境,常常想靠自已改变命运,却一次次使自已的生活走入穷困,还不如听天由命,安于本份。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="坎坷不平,艰难重重,若无耐心,难望有成",un_sign_text="人生过程中,您会遇到非常多的困难,有一坡未平一坡又起之势,在面对这些坎坷时,只要有耐心和毅力,最终都会获得成功的,否则容易一事无",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="黑暗无光,心迷意乱,出尔反尔,难定方针",un_sign_text="黑暗无光之凶运数。不仅事事不能如意,加以心迷意乱,难决定方针,出尔反尔,徒蒙损失,虽获成就。如能就初衷贯彻,或有小康之望。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="吉凶参半,得失相伴,投机取巧,如赛一样",un_sign_text="没有做太多对他人有价值的事情,导到一生来所做的事有如博彩,投机取巧,来得快也去得快,没有多少剩余,命运也在输赢之间转变。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="乌云遮月,暗淡无光,空费心力,徒劳无功",un_sign_text="有特强的第六灵感,性格率直无机心,深得朋辈爱戴。感情路上多采多姿。做事喜好凭个人直觉及预感做决定。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="虽用心计,事难遂愿,贪功好进,必招失败",un_sign_text="无论在社会中有什么地位都会被认定为最低层的人。你深深体会到社会的不公平一面,为了替贫民谋幸福,你会想尽办法改善社会的状况,尤其是",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="虽抱奇才,有才无命,独营无力,财利无望",un_sign_text="你虽然很有才,但是却没这个命(时运);事业上自己单干,是不会有什么好发展的,财利难望意思是说发财致富这个愿望是很难实现的。",), + QrFortune(fortune_summary="凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="根基不固,摇摇欲坠,一盛一衰,劳而无功",un_sign_text="与人合伙比之独营好得多,若自己独营商则中途易受挫折。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="事与愿违,终难成功,欲速不达,有始有终",un_sign_text="做事不能三分钟热度,要有始有终。急于求成,将会事与愿违,大事难成。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="忍得苦难,必有后福,是成是败,惟靠坚毅",un_sign_text="只要有坚毅的决心,肯下功夫肯吃苦,多么难的事也能做成功。成功了,福也是必然相随。",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="利不及费,坐食山空,如无智谋,难望成功",un_sign_text="入不敷出,即使有很好的基础,如果没有智谋或用人不善,难以发扬光大,最终可能败掉一切。",), + QrFortune(fortune_summary="凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="遇事犹疑,难望成事,大刀阔斧,始可有成",un_sign_text="做事犹豫、不果断,很难做成功;变得果断勇敢了,才有希望。",), + QrFortune(fortune_summary="凶",lucky_star="☆☆☆☆☆☆☆",sign_text="虽倾全力,难望成功,此数大凶,最好改名",un_sign_text="即使全力以赴,却没有取得成功。导致失败的原因是现时的待人处事方式有问题,要改变这个现状,要自我反省,改变一些令人厌恶的恶习,方可",), + QrFortune(fortune_summary="凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="秋草逢霜,怀才不遇,忧愁怨苦,事不如意",un_sign_text="秋天的枯草已经赶上了冰冷的寒霜,而我胸怀才学但生不逢时,难以施展,人生尽是这些忧愁、埋怨、苦衷,人生之事都不如意。",), + QrFortune(fortune_summary="凶带吉",lucky_star="⭐⭐⭐☆☆☆☆",sign_text="半凶半吉,浮沉多端,始凶终吉,能保成功",un_sign_text="所求之事,是吉凶参半。所要经历的,既有非你所愿、无法承受之痛苦,也有甘之如饴、顺风顺水之运气。无法如预期的稳定,不确定的因素对其",), + QrFortune(fortune_summary="凶带吉",lucky_star="⭐⭐⭐☆☆☆☆",sign_text="名虽可得,利则难获,艺界发展,可望成功",un_sign_text="可能有名气,却未能用这名气带来财运,可考虑从事娱乐或艺术来业,把名气转化成事业中一部分。",), + QrFortune(fortune_summary="凶带吉",lucky_star="⭐⭐☆☆☆☆☆",sign_text="一成一败,一盛一衰,惟靠谨慎,可守成功",un_sign_text="成败,盛衰这都是相对的,有成功就会有失败,有强盛就会有衰落这都只是时间问题,只有坚定的信念对能获得一定的成功但并不能够永久",), + QrFortune(fortune_summary="吉",lucky_star="⭐⭐⭐⭐☆☆☆",sign_text="吉运自来,能享盛名,把握机会,必获成功",un_sign_text="人生路上机会众多,只要把握好一次机会,将会改写您的人生。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="一盛一衰,浮沉不常,自重自处,可保平安",un_sign_text="人生有盛有衰,十年河西,十年河东。不论在顺利的时候的还是在倒霉的时候,都要做到自重自处,不能因胜利而洋洋自得,也不能因失败而一蹶",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="云遮半月,百隐风波,应自谨慎,始保平安",un_sign_text="最近运势不好,有对你不利的事情(不好的事情)要发生,自己办事情,说话要谨慎小心,才能避过这些。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="吉凶互见,一成一败,凶中有吉,吉中有凶",un_sign_text="一生并不顺利,在顺境时,记得要居安思危;在逆境时千万不要气馁,以您的性格,可以做到逆境中发现机会,从危机中发现生机。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="得而复失,枉费心机,守成无贪,可保安稳",un_sign_text="一生艰难辛苦,如波浪之重叠不绝,终身多受挫折而致病弱,刑罚,孤独夭寿之凶兆,若能及早修行善德,脱离凡俗而隐退者,尚可保小康之清福",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="一胜一衰,浮沉不定,知难而退,自获天佑",un_sign_text="谨慎保安勿自骄,智谋胆略得显晓,知难而退获天佑,妄进逞强败涂地。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="事业不专,十九不成,专心进取,可望成功",un_sign_text="对事业不专注者,很难有所成就,有了进取心,对事业专心致志才有成功的希望!",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐⭐☆☆☆☆",sign_text="吉凶参半,惟赖勇气,贯彻力行,始可成功",un_sign_text="人生之路吉、凶各半,有好有坏;要想改变这种不利局面,唯有依赖你的勇气和不屈服的执行力,一步步向前,人生才会更光明,更成功。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="先苦后甘,先甘后苦,如能守成,不致失败",un_sign_text="不能一生都有好运,但也不全是恶运,好坏总会各占一半,当好运来时,记得积谷防饥。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="有得有失,华而不实,须防劫财,始保平安",un_sign_text="金钱上有损失,切忌花枝招展,外表的华丽可能为您带来小人的攻击。",), + QrFortune(fortune_summary="吉带凶",lucky_star="☆☆☆☆☆☆☆",sign_text="吉中带凶,欲速不达,进不如守,可保安祥",un_sign_text="在好运中含藏凶兆,不能操之过急,不可冒然急进,前进得太快,容易出现危险,还不如坚守现在的阵地。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="雨夜之花,外祥内苦,忍耐自重,转凶为吉",un_sign_text="下雨对于花来说,是件好事,但是雨夜,像征着孤独、恐惧、所以,看似吉祥的一片,实是内心承受着煎熬。如果坚强的忍耐过雨夜的敲打,熬过",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐⭐☆☆☆☆☆",sign_text="外观隆昌,内隐祸患,克服难关,开出泰运",un_sign_text="外人看来很风光,而自已内部隐藏的危机,只要解决内部的危机,人生将会过得风风火火。",), + QrFortune(fortune_summary="吉带凶",lucky_star="⭐☆☆☆☆☆☆",sign_text="盛衰参半,外祥内苦,先吉后凶,先凶后吉",un_sign_text="一生好运与恶运都会让您遇上,当外表风光时,可能您的内心正受到非常大的困苦。前半生可能过得很苦,但后半生会出现转运,生活变得很美好",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="草木逢春,枯叶沾露,稳健着实,必得人望",un_sign_text="挽回家运矣春光,顺调发展财辉煌,温和笃实阴阳合,稳健顺调得人望。顺风满帆而容易有所成就,易取富贵人生。外缘殊胜,容易得人之助力及",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="思虑周详,计划力行,不失先机,可望成功",un_sign_text="兴家立业意志强,智虑周密名望扬,志操坚固信用重,一身才艺建基业。",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="时来运转,事事如意,功成名就,富贵自来",un_sign_text="利路享通万事成,和畅逍达四海明,家运隆盛招富贵,万商云集得繁荣。",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="万物化育,繁荣之象,专心一意,始能成功",un_sign_text="富贵荣达得显甯,子孙繁茂福绵绵,一身平安富益寿,福禄双全享千锺。",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="大展鸿图,信用得固,无远弗界,可获成功",un_sign_text="地开泰万事成,身体康安亦富荣,否泰名誉兼享福,一生无忧乐绵长。顺风满帆而容易有所成就,易取富贵人生。",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐☆☆",sign_text="有贵人助,可成大业,虽遇不幸,浮沉不大",un_sign_text="开花结子衣食足,大业奏功可庆祝,子孙繁荣多快乐,一家圆满庆有馀。",), + QrFortune(fortune_summary="大吉",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="阴阳和合,生意欣荣,名利双收,后福重重",un_sign_text="福禄寿长阴阳和,心身健全是英豪,名利双收富荣达,乃是世上福德人。财源特佳金钱有餘,离出生之地而往大都市求谋必得更发达。",), + QrFortune(fortune_summary="大吉+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="根深蒂固,蒸蒸日上,如意吉祥,百事顺遂",un_sign_text="进取富贵又如意,智达明敏扬名威,名利寿福皆此得,前途光茫好鸿图。外缘殊胜,容易得人之助力及予人好印象。",), + QrFortune(fortune_summary="大吉+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="专心经营,善用智慧,霜雪梅花,春来怒放",un_sign_text="明月光照乐依依,俟如梅花待放时,兴家立业名利全,各自独立有权威。男带此数,需要加强节制力,可免受桃花困扰。女则因事业雄心万丈,多",), + QrFortune(fortune_summary="大吉+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="富贵荣华实可当,光明荣达好儿郎,家门隆昌福万千,世代子孙个个贤。",un_sign_text="因异性而引起之纠纷困扰,失利特多,而且一生常遇逆境之折磨。家庭和顺则万事可成。智能超人贯彻大志,富贵无比,不甘寂寞,叱吒风云之大",), + QrFortune(fortune_summary="大吉+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="旭日升天,名显四方,渐次进展,终成大业",un_sign_text="旭日东昇势壮富,贯彻大业万事胜,终至荣达功名显,猛虎添翼势声强。具有此数之人,男多勇敢果断,女多貌若天仙,有风流不羁(不顾时局大",), + QrFortune(fortune_summary="大吉+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="此数大吉,名利双收,渐进向上,大业成就",un_sign_text="智勇得志意气新,建立声誉事业兴,终到富贵福禄奏,为人领导德望高。顺风满帆而容易有所成就,易取富贵人生。",), + QrFortune(fortune_summary="大吉+官运+才艺",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="天赋吉运,能得人望,善用智慧,必获成功",un_sign_text="智略超群博学多,善处事务亦忍和,功业成就得富荣,艺才相身乐千锺。外缘殊胜,容易得人之助力及予人好印象。具有此数之人,男多勇敢果断",), + QrFortune(fortune_summary="大吉+官运+财运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="能获众望,成就大业,名利双收,盟主四方",un_sign_text="贵人得助天乙扶,为人之上有财富,众望所归事业成,不可贪色保安宁。名誉良好,信用亦佳,步步高升。外缘殊胜,容易得人之助力及予人好印",), + QrFortune(fortune_summary="大吉+官运+财运+才艺",lucky_star="⭐⭐⭐⭐⭐⭐⭐",sign_text="如龙得云,青云直上,智谋奋进,才略奏功",un_sign_text="欲望难足希望高,计谋成功财力豪,猜疑嫉妒性自改,如龙乘云势运开。智能超人贯彻大志,富贵无比,不甘寂寞,叱吒风云之大吉数,但容易发",), + QrFortune(fortune_summary="大吉+才艺",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="美化丰实,鹤立鸡群,名利俱全,繁荣富贵",un_sign_text="有德且智德望高,堪为顾问得仁和,名利双收天赋富,威望荣达世间豪。",), + QrFortune(fortune_summary="大吉+财运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="谦恭做事,必得人和,大事成就,一定兴隆",un_sign_text="福寿拱照德望高,财子寿全又温和,慈祥好善可恭敬,富贵繁荣得惠泽。财源特佳金钱有餘,离出生之地而往大都市求谋必得更发达。外缘殊胜,",), + QrFortune(fortune_summary="大吉+财运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="锦绣前程,须靠自力,多用智谋,能奏大功",un_sign_text="家门余庆福无疆,子孙繁荣富贵强,白手成家立大业,财源广进智谋全。营商的话还是独营的好,与人合伙久之厌烦不耐。少年读书需用心,舟至",), + QrFortune(fortune_summary="大吉+财运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="草木逢春,雨过天晴,渡过难关,即获成功",un_sign_text="先见机明察佳期,意志坚固好运时,功名利达福禄全,一世荣隆乐绵绵。",), + QrFortune(fortune_summary="大吉+财运+官运",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="天赋吉运,德望兼备,继续努力,前途无限",un_sign_text="德望高大名誉振,才谋健全财源进,富贵荣华福禄至,前途洋洋得意真。",), + QrFortune(fortune_summary="大吉+财运+才艺",lucky_star="⭐⭐⭐⭐⭐⭐☆",sign_text="不可意气,善用智慧,如能慎始,必可昌隆",un_sign_text="家门隆昌精神爽,博得名利星月朗,权威智谋极周全,君是天下富贵翁。具有此数之人,男则勇敢果断,而女则美貌如仙子,有风流不羁不顾时",), + ] \ No newline at end of file diff --git a/src/clover_sqlite/models/tarot.py b/src/clover_sqlite/models/tarot.py new file mode 100644 index 0000000..4656364 --- /dev/null +++ b/src/clover_sqlite/models/tarot.py @@ -0,0 +1,217 @@ +import os +import random +from datetime import datetime +from tortoise import fields +from typing_extensions import Self +from src.clover_sqlite.data_init.db_connect import Model +from src.configs.path_config import tarots_img_path + + +class MajorArcanaLog: + pass + + +class MajorArcana(Model): + """ + 大阿尔克纳牌 + """ + id = fields.IntField(pk=True) + name = fields.CharField(max_length=255, unique=True, description="牌名") + upright_meaning = fields.TextField(description="正位含义") + reversed_meaning = fields.TextField(description="逆位含义") + image = fields.CharField(max_length=255, description="图片文件名") + + class Meta: + # 指定表名 + table = "major_arcana" + table_description = "大阿尔克纳牌" + + @classmethod + async def tarotChoice(cls, user_id: str | None) -> MajorArcanaLog | None: + """ + 大阿尔克纳牌抽取 + :param user_id: + :return: + """ + record = await MajorArcanaLog.getTarotLog(user_id) + if record: + return record + # 0正1逆 + ints = random.randint(0, 1) + arcana = await cls.all() + if not arcana: + await cls.bulk_create(Major_arcana_initial_data) + arcana = await cls.all() + tarots = random.choice(arcana) + # 正位 + if ints == 0: + return await MajorArcanaLog.insertTarotLog(tarots, user_id, tarots_img_path+tarots.image,"正位") + # 逆位 + if ints == 1: + return await MajorArcanaLog.insertTarotLog(tarots, user_id, tarots_img_path+tarots.image,"逆位") + + +class MajorArcanaLog(Model): + """ + 大阿尔克纳牌 + """ + id = fields.IntField(pk=True) + user_id = fields.CharField(max_length=255, description="用户id") + ints = fields.CharField(max_length=64,description="正逆") + name = fields.CharField(max_length=64, description="牌名") + meaning = fields.TextField(description="正位/逆位含义") + image = fields.CharField(max_length=255, description="图片文件名") + create_time = fields.DateField(auto_now_add=True) + + class Meta: + # 指定表名 + table = "major_arcana_log" + table_description = "大阿尔克纳牌抽取日志" + + @classmethod + async def insertTarotLog(cls, model: MajorArcana | None, user_id: str | None, image: str | None, ints:str | None) -> Self | None: + """ + 插入大阿尔克纳牌抽取日志 + :param model: + :param user_id: + :param image: + :param ints: + :return: + """ + + if ints == "正位": + meaning = model.upright_meaning + else: + meaning = model.reversed_meaning + data = { + 'user_id': user_id, + 'ints': ints, + 'name': model.name, + 'meaning': meaning, + 'image': image, + 'create_time':datetime.now().date() + } + + return await cls.create(**data) + + @classmethod + async def getTarotLog(cls, user_id: str | None ) -> Self | None: + """ + 查询大阿尔克纳牌抽取日志 + :param user_id: + :return: + """ + return await cls.filter(user_id=user_id,create_time = datetime.now().date()).first() + + +Major_arcana_initial_data = [ + MajorArcana( + name="愚者 (The Fool) ", + upright_meaning="从零开始; 好赌运; 不墨守成规; 追求新奇的梦想; 冒险; 放浪形骸; 艺术家的气质; 异于常人; 直攻要害、盲点; 爱情狩猎者; 爱情历经沧桑; 不拘形式的自由恋爱", + reversed_meaning=" 不安定; 孤注一掷会失败; 缺乏责任感; 损失; 脚跟站不稳; 堕落; 没发展; 没计划; 走错路; 行为乖张; 轻浮的恋情; 感情忽冷忽热; 不安定的爱情之旅", + image="The Fool.jpg"), + MajorArcana( + name="魔术师 (The Magician)", + upright_meaning="好的开始; 具独创性; 有发展的; 新计划成功; 想像力丰富或有好点子; 有恋情发生; 拥有默契良好的伴侣; 有新恋人出现; 值得效仿的对象出现", + reversed_meaning=" 失败; 优柔寡断; 才能平庸; 有被欺诈的危险; 技术不足; 过于消极; 没有判断力; 缺乏创造力; 爱情没有进展 ", + image="The Magician.jpg"), + MajorArcana( + name="女祭司 (The High Priestess)", + upright_meaning="知性、优秀的判断力; 具洞察力及先见之明; 强大的战斗意志; 冷静的统率力; 学问、研究等精神方面幸运; 独立自主的女性; 柏拉图式的爱情; 有心灵上交往至深的友人; 冷淡的恋情 ", + reversed_meaning=" 无知、缺乏理解力; 研究不足; 不理性的态度; 自我封闭; 神经质; 洁癖; 与女性朋友柒争执; 对人冷淡; 晚婚或独身主义; 没有结果的单相思; 气色不好; 不孕", + image="The High Priestess.jpg"), + MajorArcana( + name="皇后 (The Empress)", + upright_meaning="充满创造力与母性光辉; 生活富足、美满; 事业上有出色的规划与执行能力,易取得成果; 感情中温柔体贴,是理想的伴侣; 孕育新生命或有新的创意项目诞生", + reversed_meaning=" 创造力受阻; 生活陷入混乱,经济上可能出现问题; 感情中可能变得情绪化、占有欲强; 缺乏实际行动,计划难以实现; 健康方面可能有妇科问题", + image="The Empress.jpg"), + MajorArcana( + name="皇帝 (The Emperor)", + upright_meaning="以坚强的意志力及手腕获致成功; 富裕和力量; 有责任感; 良好的处理能力; 具领导能力; 男性的思考; 坚持到底; 虽有点专制却值得信赖; 条件诱人的提亲; 与年长者恋爱 ", + reversed_meaning=" 不成熟; 意志薄弱; 虚有其表; 看不清现实; 欠缺实务能力; 因傲慢而招人反感; 工作过度; 固执; 没有经济基础; 没有好对象; 苦恋结束; 勉强的感情", + image="The Emperor.jpg"), + MajorArcana( + name="教皇 (The Hierophant) ", + upright_meaning="受人信赖; 有贵人相助; 贡献; 受上司重视; 能胜任工作; 拥有一颗温柔的心; 受惠于有益的建言; 接触宗教的事物大吉; 与年长的异性有缘; 良缘; 深情宽大的爱; 有结良缘的机会 ", + reversed_meaning=" 没信用; 没有贵人相助; 孤立无援; 不受欢迎的好意; 依赖心是最大的敌人; 太罗嗦而讨人厌; 碍于私情而无法成功; 心胸狭窄; 得不到亲人的谅解的恋情; 彼此过于关心; 缘分浅薄的恋情 ", + image="The Hierophant.jpg"), + MajorArcana( + name="恋人 (The Lovers) ", + upright_meaning="幸运的结合; 有希望的将来; 有共同做事的伙伴; 与人合作或社团活动; 敏感决定前进之路的好时机; 有意气相投的朋友; 爱情机会将到来; 罗曼蒂克的恋情; 爱的预感", + reversed_meaning=" 分离; 消解; 不合作的态度; 眼花缭乱; 没有满意的成果; 无法持续; 退休; 妨碍; 血气方刚; 多情的人; 分手; 冷漠的爱; 背信; 逃避爱情; 短暂的恋情", + image="The Lovers.jpg"), + MajorArcana( + name="战车 (The Chariot)", + upright_meaning="前进必胜; 先下手为强; 独立; 起程; 在颠簸中仍有好成绩; 活泼; 有野心; 以速度取胜; 有开拓精神; 握有指挥权; 战胜敌手; 富行动力的恋情; 恋爱的胜利者 ", + reversed_meaning=" 失败; 丧失战斗意志; 状态不佳; 挫折; 性子过急为失败之因; 不感兴趣; 效率不佳; 资金运转困难; 无奋斗精神; 有强劲敌手进入; 被拒绝; 因怯懦而使恋情不顺 ", + image="The Chariot.jpg"), + MajorArcana( + name="力量 (Strength) ", + upright_meaning="不屈不挠的精神; 将不可能化为可能的意志力; 全力以赴; 突破难关; 坚强的信念和努力; 挑战已知危险的勇气; 神秘的力量; 旺盛的斗志; 轰轰烈烈的恋情; 克服困难的真实爱情", + reversed_meaning=" 疑心病; 犹豫不决; 实力不足; 无忍耐力; 危险的赌注; 勉强为之而适得其反; 丧失自信; 喜欢故弄玄虚; 体力不足; 自大自负; 误用力气 ", + image="Strength.jpg"), + MajorArcana( + name="隐士 (The Hermit) ", + upright_meaning="智能与卓越见解; 不断地追求更高层次的东西; 思虑周密; 冷静沉着; 不多言; 接触知性事物吉; 正中核心的建言; 活动慢慢进行较有成果; 出局; 追求柏拉图式的爱情; 暗中的爱情", + reversed_meaning=" 一视同仁; 不够通融; 不专心易生错误; 过分警戒,无法顺利进行; 秘密泄漏; 过于固执不听别人的意见; 孤独; 动机不单纯; 因怨言及偏见招人嫌; 轻浮的爱情; 怀疑爱情", + image="The Hermit.jpg"), + MajorArcana( + name="命运之轮 (The Wheel of Fortune) ", + upright_meaning="机会到来; 随机应变能力佳; 好运; 转换期; 意想不到的幸运; 升迁有望; 变化丰富; 好时机; 宿命的相逢; 一见钟情; 幸运的婚姻; 富贵的身份 ", + reversed_meaning=" 低潮期; 时机未到; 评估易出错; 时机不好; 没有头绪; 处于劣势; 生活艰苦; 情况恶化; 计划停滞需要再等待; 失恋; 短暂的恋情; 易错失良机; 不敌诱惑; 爱情无法持久 ", + image="The Wheel of Fortune.jpg"), + MajorArcana( + name="正义 (Justice)", + upright_meaning="公正; 严正的意见; 良好的均衡关系; 严守中立立场; 凡事合理化; 身兼两种工作; 协调者; 与裁判、法律相关者; 表里一致的公正人物; 以诚实之心光明正大地交往; 彼此能获得协调 ", + reversed_meaning=" 不公正; 不平衡; 不利的条件; 偏颇; 先入为主的观念; 偏见与独断; 纷争、诉讼; 问心有愧; 无法两全; 天平两边无法平衡; 性格不一致; 无视于社会道德观的恋情; 偏爱", + image="Justice.jpg"), + MajorArcana( + name="倒吊人 (The Hanged Man)", + upright_meaning="接受考验; 无法动弹; 被牺牲; 有失必有得; 从痛苦的体验中获得教训; 过度期; 不贪图眼前利益; 浴火重生; 多方学习; 奉献的爱; 明知辛苦但全力以赴", + reversed_meaning=" 无谓的牺牲; 折断骨头; 有噩运、居于劣势; 任性妄为; 不努力; 变得没有耐性; 利己主义者; 受到惩罚; 无偿的爱; 缺乏共同奋斗的伙伴", + image="The Hanged Man.jpg"), + MajorArcana( + name="死神 (Death)", + upright_meaning="失败; 毁灭之日将近; 损害继续延续; 失业; 进展停滞; 交易停止; 为时已晚; 停滞状态; 生病或意外的暗示; 味如嚼蜡的生活; 不幸的恋情; 恋情终止; 彼此间有很深的鸿沟; 别离 ", + reversed_meaning=" 起死回生的机会; 脱离低迷期; 改变印象; 回心转意再出发; 挽回名誉; 奇迹似地康复; 突然改变方针; 已经死心的事有了转机; 斩断情丝,重新出发", + image="Death.jpg"), + MajorArcana( + name="节欲 (Temperance) ", + upright_meaning="单纯化; 顺畅; 交往平顺; 两者相融顺畅; 调整; 彼此交换有利条件; 平凡中也有重要的契机; 平顺的心境; 纯爱; 从好感转为爱意; 深爱 ", + reversed_meaning=" 消耗; 每节制的损耗,对身心产生不好的影响; 疲劳; 不定性的工作; 缺乏调整能力; 下降; 浪费; 不要与人 合作; 不融洽; 爱情的配合度不佳 ", + image="Temperance.jpg"), + MajorArcana( + name="恶魔 (The Devil)", + upright_meaning="被束缚; 堕落; 恶魔的私语; 卑躬屈膝; 欲望的俘虏; 荒废的生活; 举债度日; 病魔入侵; 夜游过多; 不可告人的事; 恶意; 不可抗拒的诱惑; 私密恋情; 沉溺于感官刺激之下", + reversed_meaning=" 逃离拘束; 长期的苦恼获得解放; 斩断前缘; 越过难关; 暂时停止; 拒绝诱惑; 舍弃私欲; 治愈长期病痛; 别离 时刻; 如深陷泥沼爱恨交加的恋情", + image="The Devil.jpg"), + MajorArcana( + name="塔 (The Tower) ", + upright_meaning="致命的打击; 纷争; 纠纷不断; 与周遭事物对立,情况恶化; 意想不到的事情; 急病; 受牵连; 急剧的大变动; 信念奔溃; 逆境; 破产; 没有预警,突然分离; 破灭的爱; 玩火自焚", + reversed_meaning=" 紧迫的状态; 险恶的气氛; 内讧; 即将破灭; 急需解决的问题; 承受震撼; 背水一战; 注意刑事问题; 因骄傲自大将付出惨痛的代价; 状况不佳; 困境; 爱情危机; 分离的预感 ", + image="The Tower.jpg"), + MajorArcana( + name="星辰 (The Star) ", + upright_meaning="愿望达成; 前途光明; 充满希望的未来; 美好的生活; 曙光出现; 大胆的幻想; 水准提高; 新的创造力; 想像力; 理想的对象; 美好的恋情; 爱苗滋生 ", + reversed_meaning=" 挫折、失败; 理想过高; 缺乏想像力; 异想天开; 事与愿违; 失望; 从事不喜欢的工作; 好高骛远; 情况悲观; 不可期待的对象; 没 有爱的生活; 秘密恋情; 仓皇失措", + image="The Star.jpg"), + MajorArcana( + name="月亮 (The Moon) ", + upright_meaning="不安与动摇; 心中不平静; 谎言; 暧昧不明; 鬼迷心窍; 暗藏动乱; 欺骗; 终止; 不安的爱; 三角关系", + reversed_meaning=" 从危险的骗局中逃脱; 状况稍为好转; 误会冰释; 破除迷惘; 时间能解决一切; 眼光要长远; 静观等待; 早期发现早期治疗有效; 事前察知危险; 对虚情假意的恋情已不在乎 ", + image="The Moon.jpg"), + MajorArcana( + name="太阳 (The Sun)", + upright_meaning="丰富的生命力; 巨大的成就感; 人际关系非常好; 爱情美满; 内心充满了热情和力量; 一定能够实现的约定; 飞黄腾达; 无忧无虑", + reversed_meaning=" 情绪低落; 事情失败; 朋友的离去和人际关系的恶化; 无法安定内心; 忧郁孤单寂寞; 爱情不顺 利; 取消的计划; 工作上困难重重 ", + image="The Sun.jpg"), + MajorArcana( + name="审判 (Judgement)", + upright_meaning="复活的喜悦; 开运; 公开; 改革期; 危机解除; 决断; 荣升; 崭露头角; 好消息; 爱的使者; 恢复健康; 坦白; 复苏的爱; 再会; 爱的奇迹 ", + reversed_meaning="一败不起; 幻灭; 离复苏还有很长的时间; 不利的决定; 不被采用; 还未开始就结束了; 坏消息; 延期; 无法决定; 虽重新开始,却又恢复原状; 分离、消除; 恋恋不舍", + image="Judgement.jpg"), + MajorArcana( + name="世界 (The World)", + upright_meaning="完成; 成功; 拥有毕生的志业; 达成目标; 永续不断; 最盛期; 完美无缺; 接触异国,将获得幸运; 到达标准; 精神亢奋; 快乐的结束; 模范情侣 ", + reversed_meaning=" 未完成; 无法达到计划中的成就; 因准备不足而失败; 中途无法在进行; 不完全燃烧; 一时不顺利; 饱和状态; 烦恼延续; 精神松弛; 个人惯用的表现方式; 因不成熟而 使情感受挫; 合谋; 态度不够圆融", + image="The World.jpg")] diff --git a/src/clover_sqlite/models/to_do.py b/src/clover_sqlite/models/to_do.py new file mode 100644 index 0000000..76094dc --- /dev/null +++ b/src/clover_sqlite/models/to_do.py @@ -0,0 +1,59 @@ +from tortoise import fields +from typing_extensions import Self +from src.clover_sqlite.data_init.db_connect import Model + + +class ToDoList(Model): + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + user_id = fields.CharField(max_length=64, description="用户member_openid") + content = fields.TextField() + + class Meta: + table = "user_todo_list" + table_description = "用户待办表" + + @classmethod + async def _get_data(cls, user_id: str | None) -> list | None: + """ + 获取对应用户的待办 + """ + if not user_id: + return None + else: + return await cls.filter(user_id=user_id).order_by("id").values_list("id", "user_id", "content") + + @classmethod + async def get_todo_list(cls, user_id: str | None) -> Self | None: + todo_table = await cls._get_data(user_id) + todo_list = [row[2] for row in todo_table] + if todo_list: + return todo_list + else: + return False + + @classmethod + async def insert_todo_list(cls, user_id: str | None, content: str | None) -> bool: + + if content.lstrip(" ") == "": + return False + data = { + "user_id": user_id, + "content": content + } + await cls.create(**data) + return True + + @classmethod + async def delete_user_todo(cls, user_id: str | None, del_line_num: int | None) -> int: + todo_table = await cls._get_data(user_id) + + if not todo_table: + return -1 + + max_length = len(todo_table) + if del_line_num > max_length or del_line_num < 1: + return 1 + + del_id = todo_table[del_line_num - 1][0] + await cls.filter(id=del_id).delete() + return 0 diff --git a/src/clover_sqlite/models/touch.py b/src/clover_sqlite/models/touch.py new file mode 100644 index 0000000..0536956 --- /dev/null +++ b/src/clover_sqlite/models/touch.py @@ -0,0 +1,116 @@ +from datetime import datetime +import random +from tortoise import fields +from typing_extensions import Self +from src.clover_sqlite.data_init.db_connect import Model + + +class QrTouch(Model): + """ + 摸头回复内容 + """ + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + touch_status = fields.IntField(default=0,description="状态", null=True) + reply_touch_content = fields.CharField(max_length=255, description="响应内容", null=True) + class Meta: + # 指定表名 + table = "qr_touch" + table_description = "rua回复内容" + + @classmethod + async def touch(cls, status: int | None)-> Self | None: + """ + 获取摸头内容 + :param status: + :return: + """ + existing_record = await QrTouch.filter(touch_status=status).all() + if not existing_record: + # 执行初始化 + await cls.bulk_create(touch_initial_data) + existing_record = await QrTouch.filter(touch_status=status).all() + return random.choice(existing_record) + + +class QrTouchLog(Model): + """ + 摸头记录 + """ + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + touch_status = fields.IntField(default=0,description="状态", null=True) + reply_touch_content = fields.CharField(max_length=255, description="响应内容", null=True) + user_id = fields.CharField(max_length=64, description="用户id", null=True) + extract_time = fields.DateField(description="日期", null=True) + class Meta: + # 指定表名 + table = "qr_touch_log" + table_description = "rua回复内容" + + @classmethod + async def insert_touch_log(cls, model:QrTouch, member_openid): + """ + 插入摸头记录 + :param model: + :param member_openid: + :return: + """ + data = { + "touch_status": model.touch_status, + "reply_touch_content": model.reply_touch_content, + "user_id": member_openid, + "extract_time": datetime.now().date() + } + await cls.create(**data) + + @classmethod + async def touch_count(cls, member_openid): + """ + 获取摸头次数 + :param member_openid: + :return: + """ + result = await QrTouchLog.filter(user_id=member_openid, extract_time=datetime.now().date()).count() + return result + +touch_initial_data = [QrTouch(touch_status=0,reply_touch_content="哼!你怎么突然摸我的头,把我吓了一跳!我刚刚整理好的毛发都被你弄乱了啦,你得负责帮我重新梳理好哦,喵!"), + QrTouch(touch_status=0,reply_touch_content="哼,真是的,又来摸本喵的头。虽然……虽然也不是很讨厌,但你可别得寸进尺哦,不然我就用爪子抓你啦!喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~你在摸我的头呢,好舒服呀!感觉就像被柔软的云朵轻轻拂过一样呢再用点力也没关系哦,我可是很享受的呢。"), + QrTouch(touch_status=0,reply_touch_content="嘿,人类,你以为摸我的头就能讨好我啦?不过看在你手法还不错的份上,这次就允许你啦,喵~但要记得给我准备小鱼干哦。"), + QrTouch(touch_status=0,reply_touch_content="喵呜~别停呀,你的摸头动作真是太棒啦,让我想起了妈妈舔我的感觉呢,我都快融化啦~"), + QrTouch(touch_status=0,reply_touch_content="嘻嘻,你在给我挠痒痒呢,真是太有趣啦!我要在你身边转圈圈啦,多摸摸我的头,我会更加爱你的哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="哼,虽然我是一只高傲的猫,但被你摸摸头的感觉还不赖哦不过,你可得小心点,要是把我惹毛了,我可是会亮出爪子的哦,喵!"), + QrTouch(touch_status=0,reply_touch_content="喵~你的手好温暖呀,每次被摸摸头,我就觉得自己是世界上最幸福的猫咪啦,希望你能一直这样摸下去呢。"), + QrTouch(touch_status=0,reply_touch_content="喵!你在摸我的头,这是在向我表示友好吗?那我就勉为其难地接受啦,要是能再给我一些猫薄荷就更好啦~"), + QrTouch(touch_status=0,reply_touch_content="呜呜~被摸摸头的感觉好温馨哦,我都想在你的腿上睡一觉啦,记得要一直摸着我,不然我会生气的哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="嘿,你的摸头让我感觉自己像个小宝贝呢,我会用最可爱的样子来报答你哦,多摸摸我的头,让我更加可爱吧,喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~我喜欢这种被抚摸的感觉呢,就像沉浸在温暖的阳光中,你可以多摸摸我的头,这样我会更有活力哦,说不定会帮你抓到更多老鼠呢。"), + QrTouch(touch_status=0,reply_touch_content="喵呜~好啦好啦,我已经被你摸得服服帖帖啦,感觉自己的毛都变得更加顺滑啦,继续保持哦,我会更听你的话呢。"), + QrTouch(touch_status=0,reply_touch_content="你在摸我的头,是不是觉得我很可爱呀我可以让你多摸一会儿,不过作为交换,你要陪我玩捉迷藏哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~谢谢你的摸头啦,你真是个好人呢,我会给你带来好运的哦,就像招财猫一样,只要你继续给我摸摸头,喵~"), + QrTouch(touch_status=0,reply_touch_content="嘿,你这个铲屎官,摸头的动作还挺熟练嘛,我允许你再摸一会儿啦,不过可别想随便摸我的尾巴哦,喵!"), + QrTouch(touch_status=0,reply_touch_content="喵~你的摸头就像一场温柔的冒险,让我沉浸其中呢,希望你能多摸摸我,我会带你去探索很多有趣的地方哦。"), + QrTouch(touch_status=0,reply_touch_content="喵呜~被摸摸头真是太美妙啦,感觉自己的九条命都变得更加精彩啦,你是我最喜欢的人类啦,继续给我摸摸头吧。"), + QrTouch(touch_status=0,reply_touch_content="哼,虽然我很傲娇,但我不得不承认,被你摸摸头的感觉真的很棒哦,不过,你可别太得意啦,喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~我感觉自己像一只被宠爱的小猫咪,你是我最信任的人啦,多摸摸我的头,我会在你身边撒娇哦。"), + QrTouch(touch_status=0,reply_touch_content="呜呜~被摸摸头的时候,我觉得自己是最幸福的啦,希望你能一直守护我,就像我守护自己的小鱼干一样,喵~"), + QrTouch(touch_status=0,reply_touch_content="嘿,你在摸我的头呢,是不是在给我施展魔法呀我已经被你的魔法控制啦,要一直摸下去哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~每次你摸我的头,我就会变得更加慵懒哦,我会躺在你的怀里,享受这种惬意的时光,希望你能多陪陪我呢。"), + QrTouch(touch_status=0,reply_touch_content="喵呜~你的摸头让我变得更加放松啦,我会像猫精灵一样为你带来快乐,只要你不停止给我摸头哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="嘿,别以为摸我的头是一件简单的事情哦,这可是需要技巧的呢,不过你现在做得还不错啦,继续加油哦,喵~"), + QrTouch(touch_status=0,reply_touch_content="喵~我要把我的头靠在你手上啦,这样你就可以更方便地摸我啦,我会发出咕噜咕噜的声音来表示我的快乐哦。"), + QrTouch(touch_status=0,reply_touch_content="呜呜~你是在给我按摩吗?我太喜欢啦,我会用最可爱的动作来感谢你,多摸摸我的头,我会更有精神哦,喵~"), + QrTouch(touch_status=1,reply_touch_content="喵!你这家伙到底有完没完?!再敢碰我的头一下,我就把这房间里的东西全部抓烂,让你见识见识我的厉害!"), + QrTouch(touch_status=1,reply_touch_content="嘶嘶——离我远点!你这不知死活的家伙,摸我的头?你是想尝尝我的爪子有多锋利吗?我可不会手下留情!"), + QrTouch(touch_status=1,reply_touch_content="喵呜!!我警告你,立刻停止你的动作!你要是再敢侵犯我的领地(头部),我就趁你睡觉的时候在你脸上留下几道漂亮的爪痕,让你知道我的愤怒!"), + QrTouch(touch_status=1,reply_touch_content="哼!你以为你是谁?竟敢摸本大爷/大小姐的头!我现在就去把你的鞋子咬得稀巴烂,看你还敢不敢乱动!"), + QrTouch(touch_status=1,reply_touch_content="喵!!!我已经忍无可忍了!你这无礼的行为简直不可饶恕,我要发动我的猫之诅咒,让你接下来的日子诸事不顺,除非你马上把手拿开!"), + QrTouch(touch_status=1,reply_touch_content="别逼我使出绝招!你再摸一下试试,我就把你心爱的那些小物件一个个从桌子上推下去摔碎,让你为你的鲁莽付出代价!"), + QrTouch(touch_status=1,reply_touch_content="喵!你是不是瞎啊?没看到我浑身的毛都因为生气竖起来了吗?还不把手缩回去,我马上就扑上去咬断你的手指!"), + QrTouch(touch_status=1,reply_touch_content="嘶——我可不是好惹的!你这愚蠢的人类,摸我的头就像在挑战我的威严,我会让你知道什么叫恐惧,等着瞧吧!"), + QrTouch(touch_status=1,reply_touch_content="喵呜!!你触碰到了我的底线,我现在就去把你藏在角落里的零食找出来吃掉,一颗都不给你留,这就是你摸我头的下场!"), + QrTouch(touch_status=1,reply_touch_content="哼,摸什么摸呀,烦死了!你就不能让我清净会儿吗?别老想着动手动脚的,真当我好脾气呢!"), + QrTouch(touch_status=1,reply_touch_content="啧,又来摸我的头,你是有多无聊啊!我可没那闲工夫陪你玩这幼稚的把戏,离我远点啦!"), + QrTouch(touch_status=1,reply_touch_content="够了够了!别碰我头了行不行,每次都这样,我都快被你摸得不耐烦了,再这样我可真要发火了啊!"), + QrTouch(touch_status=1,reply_touch_content="我警告你最后一次,别碰我的头!你这没完没了的样子真的太讨厌了,小心我对你不客气!"), + QrTouch(touch_status=1,reply_touch_content="啊!你怎么还摸啊,我都想抓狂了,你是听不懂人话吗?再摸我就把你手给剁了,烦死了!"), + ] \ No newline at end of file diff --git a/src/clover_sqlite/models/user.py b/src/clover_sqlite/models/user.py new file mode 100644 index 0000000..e9fa579 --- /dev/null +++ b/src/clover_sqlite/models/user.py @@ -0,0 +1,111 @@ +from datetime import datetime, timedelta +import random +from tortoise import fields +from src.clover_sqlite.data_init.db_connect import Model + +class UserList(Model): + user_id = fields.CharField(max_length=64, description="用户member_openid") + group_id = fields.CharField(max_length=64, description="用户所在群聊id") + last_used_time = fields.DateField(auto_now_add=True, description="用户最近一次使用时间") + + class Meta: + table = "user_list" + table_description = "用户表" + + + @classmethod + async def get_user_id(cls, user_id: str | None, group_id: str | None, days: int = 3) -> str | None: + """ + 获取指定天数内有活动的用户ID,并随机选择一个作为伴侣ID。 + + :param user_id: 用户ID + :param group_id: 群组ID + :param days: 最近活动天数,默认为3天 + :return: 随机选择的伴侣ID,如果没有符合条件的用户则返回None + """ + # 检查用户是否已有伴侣 + has_wife = await Wife.has_wife(user_id=user_id, group_id=group_id) + if has_wife: + return has_wife + + # 获取最近指定天数内有活动的用户 + start_date = datetime.now().date() - timedelta(days=days) + end_date = datetime.now().date() + user_ids = await cls.filter(group_id=group_id, last_used_time__range=(start_date, end_date)) \ + .exclude(user_id=user_id).values_list("user_id", flat=True) + + if user_ids: + wife_id = random.choice(user_ids) + await Wife.save_wife(user_id=user_id, group_id=group_id, wife_id=wife_id) + return wife_id + else: + return None + + @classmethod + async def insert_user(cls, user_id: str | None, group_id: str | None): + """ + 插入用户数据 + :param user_id: + :param group_id: + :return: + """ + user_table = await cls.filter(user_id=user_id, group_id=group_id).first() + if user_table: + user_table.last_used_time = datetime.now().date() + await user_table.save() + else: + await cls.create(user_id=user_id,group_id=group_id,last_used_time=datetime.now().date()) + + +class Wife(Model): + """ + 群今日老婆记录表(包含群老婆和二次元老婆) + """ + id = fields.IntField(primary_key=True, generated=True, auto_increment=True) + user_id = fields.CharField(max_length=64, description="用户id", null=True) + group_id = fields.CharField(max_length=64, description="群聊id", null=True) + wife_id = fields.CharField(max_length=64, description="对应群聊用户抽取到的id", null=True) + wife_name = fields.CharField(max_length=64, description="名称", null=True) + wife_description = fields.CharField(max_length=64, description="描述", null=True) + create_time = fields.DateField(auto_now_add=True, description="创建时间", null=True) + + class Meta: + # 指定表名 + table = "wife" + table_description = "群今日老婆记录表" + + + + @classmethod + async def has_wife(cls, user_id: str | None, group_id: str | None) -> str | None: + """ + 查询是否有今日群老婆 + :param user_id: + :param group_id: + :return: + """ + + wife = await cls.filter(user_id=user_id, group_id=group_id, create_time=datetime.now().date()).first() + if wife is None: + return None + else: + return wife.wife_id + + @classmethod + async def save_wife(cls, user_id: str | None, group_id: str | None, wife_id: str | None): + """ + 保存今日群老婆 + :param user_id: + :param group_id: + :param wife_id: + :return: + """ + data = { + "user_id":user_id, + "group_id":group_id, + "wife_id":wife_id, + "create_time":datetime.now().date() + } + await cls.create(**data) + + diff --git a/src/clover_videos/billibili/biliVideos.py b/src/clover_videos/billibili/biliVideos.py new file mode 100644 index 0000000..019132e --- /dev/null +++ b/src/clover_videos/billibili/biliVideos.py @@ -0,0 +1,178 @@ +import os +import pickle + +import ffmpeg +import requests +import hashlib +import urllib.parse +from selenium import webdriver +from selenium.webdriver.chrome.options import Options +from src.configs.path_config import video_path + +chrome_options = Options() +chrome_options.add_argument("--headless") + +headers0 = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36", +} + +if not os.path.exists('bili.cookie'): + # # 使用Selenium模拟浏览器获取Cookie + driver = webdriver.Chrome(options=chrome_options) + driver.get("https://www.bilibili.com") + # cookies = driver.get_cookies() + with open('bili.cookie', 'wb') as f: + pickle.dump(driver.get_cookies(), f) + driver.quit() + # with requests.Session() as session: + # + # login_response = session.post("https://www.bilibili.com/") + # + # cookies = session.cookies + # + # # 保存 Cookie 到文件 + # with open('bili.cookie', 'w') as f: + # for cookie in cookies: + # f.write(f"{cookie.name}={cookie.value}; ") + +cookies = pickle.load(open('bili.cookie', 'rb')) +# with open('bili.cookie', 'r') as f: +# cookies = f.read() + +headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36", + "referer": "https://www.bilibili.com/", + "Cookie": "; ".join([f"{c['name']}={c['value']}" for c in cookies]) +} + + + +appkey = '1d8b6e7d45233436' +appsec = '560c52ccd288fed045859ed18bffd973' + + +def appsign(params, appkey, appsec): + """为请求参数进行 APP 签名""" + params.update({'appkey': appkey}) + params = dict(sorted(params.items())) # 按照 key 重排参数 + query = urllib.parse.urlencode(params) # 序列化参数 + sign = hashlib.md5((query+appsec).encode()).hexdigest() # 计算 api 签名 + params.update({'sign':sign}) + return params + + +def get_video_info(keyword): + params = { + 'search_type': 'video' + } + + signed_params = appsign(params, appkey, appsec) + query = urllib.parse.urlencode(signed_params) + url = f"https://api.bilibili.com/x/web-interface/search/type?keyword={keyword}&" + + session = requests.session() + session.get("https://www.bilibili.com/", headers=headers) + response = session.get(url + query, headers=headers).json() + # print(response['code']) + return response + +def get_video_info_bv(keyword): + params = { + 'bvid': keyword + } + + signed_params = appsign(params, appkey, appsec) + query = urllib.parse.urlencode(signed_params) + url = "https://api.bilibili.com/x/web-interface/view?&" + session = requests.session() + session.get("https://www.bilibili.com/", headers=headers) + response = session.get(url + query, headers=headers).json() + return response + +def get_video_pages_info(keyword): + """ + 通过BV号获取视频信息 + + :param keyword: + + :return: + len(vid_pages_info_list): 视频集数->int + vid_pages_info_list: 视频分集信息->dict + vid_title: 视频标题->str + vid_author: 视频UP主->str + vid_pic: 视频封面URL->str + """ + response = get_video_info_bv(keyword) + vid_pages_info_list = response['data']['pages'] + vid_title = response['data']['title'] + vid_author = response['data']['owner']['name'] + vid_pic = response['data']['pic'] + return len(vid_pages_info_list), vid_pages_info_list, vid_title, vid_author, vid_pic + +def get_video_pages_cid(vid_pages_info_list, num): + cid = vid_pages_info_list[num - 1]['cid'] + return cid + +def get_video_file_url(bvid, cid): + params = { + 'bvid': bvid, + 'cid': cid, + 'qn': '64', + 'platform': 'html5' + } + + signed_params = appsign(params, appkey, appsec) + query = urllib.parse.urlencode(signed_params) + url = "https://api.bilibili.com/x/player/playurl?&" + + session = requests.session() + session.get("https://www.bilibili.com/", headers=headers) + response = session.get(url + query, headers=headers).json() + + file_url = response['data']['durl'][0]['url'] + + return file_url + +def video_download(file_url, cid): + response = requests.get(file_url, headers=headers,stream=True) + + # 检查请求是否成功 + if response.status_code == 200: + # 将视频保存到本地文件 + with open(video_path + f'/{cid}.mp4', 'wb') as file: + for chunk in response.iter_content(chunk_size=8192): + if chunk: + file.write(chunk) + print("视频下载完成") + else: + print(f"下载失败,状态码:{response.status_code}") + +def delete_video(cid): + # 指定要删除的文件路径 + file_path = video_path + f"/{cid}.mp4" + + # 检查文件是否存在 + if os.path.exists(file_path): + # 删除文件 + os.remove(file_path) + print(f"文件 {file_path} 已被删除。") + else: + print(f"文件 {file_path} 不存在。") + +def transcode_video(input_file, output_file): + try: + # 转码视频为 H.264 编码 + ( + ffmpeg.input(input_file) + .output(output_file, c="libx264", crf=23, preset="veryfast") + .run(capture_stdout=True, capture_stderr=True) + ) + print(f"视频转码完成,输出文件:{output_file}") + except ffmpeg.Error as e: + print(f"转码失败:{e.stderr.decode()}") + +if __name__ == "__main__": + print(get_video_info('海南某211台风过后现状111')) + print(get_video_file_url('BV1p2PDeEENs', '28194047730')) + + print(get_video_pages_info('BV1p2PDeEENs')) diff --git a/src/clover_yuc_wiki/yuc_wiki.py b/src/clover_yuc_wiki/yuc_wiki.py new file mode 100644 index 0000000..08666a7 --- /dev/null +++ b/src/clover_yuc_wiki/yuc_wiki.py @@ -0,0 +1,120 @@ +import os +from pathlib import Path +import requests +from os import getcwd +from bs4 import BeautifulSoup +from datetime import datetime +from nonebot_plugin_htmlrender import template_to_pic +from src.configs.path_config import yuc_wiki_path + +base_url = "https://yuc.wiki/" +new = "https://yuc.wiki/new" + +async def get_yuc_wiki(keyword): + """ + 获取当季动漫 + """ + try: + if keyword == '本季新番': + template_name = await generate_season_url() + response = requests.get(base_url + f'{template_name}', timeout=10) + else: + template_name = 'forecast_anime' + response = requests.get(new, timeout=10) + + soup = await dispose_html(response) + with open(yuc_wiki_path+f'{template_name}.html', 'w', encoding='utf-8') as f: + f.write(str(soup)) + await get_yuc_wiki_image(template_name,568,1885) + except (Exception, IOError) as e: + print(f"Error occurred: {e}") + + return yuc_wiki_path+f'{template_name}.jpeg' + +async def generate_season_url(): + """ + 获取当前季度 + :return: + """ + now = datetime.now() + quarter_month = ((now.month - 1) // 3) * 3 + 1 + return f"{now.year}{quarter_month:02d}" + +async def dispose_html(response): + """ + 处理html + :param response: + :return: + """ + response.raise_for_status() + soup = BeautifulSoup(response.text, 'html.parser') + # 删除第一个 table 标签 + first_table = soup.select_one('table') + if first_table: + first_table.decompose() + # 批量处理需要删除的标签 + for tag in soup.select('header, aside'): + tag.decompose() + + # 查找第二个
标签 + hr_tags = soup.find_all('hr') + if len(hr_tags) >= 2: + second_hr = hr_tags[1] + # 删除第二个
标签之后的所有内容 + next_element = second_hr.next_sibling + while next_element: + next_sibling = next_element.next_sibling + next_element.extract() + next_element = next_sibling + + # 统一处理资源路径 + for tag in soup.find_all(['a', 'link', 'img', 'script', 'source']): + # 处理图片懒加载 + if tag.name == 'img' and tag.get('data-src'): + tag['src'] = tag['data-src'] + del tag['data-src'] + # 统一修正路径 + attr = 'href' if tag.name in ['a', 'link'] else 'src' + if tag.has_attr(attr): + path = tag[attr].lstrip('/\\') + if not path.startswith(('http://', 'https://')): + tag[attr] = f"{base_url}{path}" + if path.startswith('http://'): + tag[attr] = path.replace('http://', 'https://', 1) + return soup + +async def get_yuc_wiki_image(template_name,width,height): + + file = Path() / yuc_wiki_path / f"{template_name}.jpeg" + if os.path.exists(file): + with file.open("rb") as image_file: + return image_file.read() + + image_bytes = await template_to_pic( + template_path=yuc_wiki_path, + template_name=f'{template_name}.html', + templates={"data": None}, + quality=90, + type="jpeg", + pages={ + "viewport": {"width": width, "height": height}, + "base_url": f"file://{getcwd()}", + }, + wait=2, + ) + await save_img(image_bytes,template_name) + +async def save_img(data: bytes,template_name : str): + + """ + 保存yuc_wiki图片 + :param template_name: + :param data: + :return: + """ + file_path = yuc_wiki_path + f"{template_name}.jpeg" + with open(file_path, "wb") as file: + file.write(data) + print("保存图片完成") + + diff --git a/src/configs/api_config_example.py b/src/configs/api_config_example.py new file mode 100644 index 0000000..52a2efb --- /dev/null +++ b/src/configs/api_config_example.py @@ -0,0 +1,35 @@ +app_id="" +bot_account= "" + +""" +图床配置 +""" +# SMMS图床相关配置 +smms_token= "" # sm.ms图床的token +smms_image_upload_history= "https://sm.ms/api/v2/upload_history" # sm.ms图床获取上传图片历史API地址 + +# 聚合图床相关配置 +ju_he_token= "" # 聚合图床的token +ju_he_image_list= "https://api.superbed.cn/timeline" # 聚合图床获取上传图片历史API地址 + +""" +AI +""" +admin_password= "123456" # 默认注册管理员密码 +# 图灵机器人相关配置 +v3url= "https://api.vveai.com/v1/chat/completions" +v3key= "" +# DeepSeek相关配置 +deepseek_url= "https://api.deepseek.com" +deepseek_key= "" + +""" +Wenku8账号 +""" +wenku8_username = "" +wenku8_password = "" + +""" +多米HTTP代理api +""" +proxy_api = "" \ No newline at end of file diff --git a/src/configs/config.py b/src/configs/config.py new file mode 100644 index 0000000..efc7589 --- /dev/null +++ b/src/configs/config.py @@ -0,0 +1,47 @@ + +from pydantic import BaseModel + + +class BotSetting(BaseModel): + """" + Bot 配置 + """ + #数据库链接 + db_url: str = "sqlite://./chat_bot.db" + # 超级用户 + platform_superusers = {"QQ": [""]} + #官bot id:账号id + bot_id_data = {"BOT_ACCOUNT":"bot1","BOT_APPID": "user1",} + + def get_bot_uid(self, bot_id: str) -> str | None: + """获取官bot账号id + + 参数: + bot_id: 官bot id + + 返回: + str: 账号id + """ + return self.bot_id_data.get(bot_id) + + def get_superuser(self, platform: str) -> list[str]: + """获取超级用户 + + 参数: + platform: 对应平台 + + 返回: + list[str]: 超级用户id + """ + if self.platform_superusers: + return self.platform_superusers.get(platform, []) + return [] + + def get_sql_type(self) -> str: + """获取数据库类型 + + 返回: + str: 数据库类型, postgres, mysql, sqlite + """ + return self.db_url.split(":", 1)[0] if self.db_url else "" + diff --git a/src/configs/path_config.py b/src/configs/path_config.py new file mode 100644 index 0000000..76d52d3 --- /dev/null +++ b/src/configs/path_config.py @@ -0,0 +1,58 @@ +import os +from pathlib import Path + +path = os.getcwd()+'/src/resources' + + +# 塔罗牌图片路径 +image_local_qq_image_path = path+'/image/qq_image' +os.makedirs(image_local_qq_image_path, exist_ok=True) +# 个人图片路径 +image_local_path= path+"/image/MaoYuNa" +os.makedirs(image_local_path, exist_ok=True) +# 塔罗牌图片路径 +tarots_img_path = path+'/image/tarot/TarotImages/' +os.makedirs(tarots_img_path, exist_ok=True) +# 摸摸头图片路径 +rua_png = path+'/image/rua/' +os.makedirs(rua_png, exist_ok=True) +# 喜报、悲报图片路径 +good_bad = path+'/image/good_bad_news/' +os.makedirs(good_bad, exist_ok=True) +#谁说 生成图片路径 +who_say_path = path+'/image/who_say/' +os.makedirs(who_say_path, exist_ok=True) +# 日报 +daily_news_path = path+'/image/report/' +os.makedirs(daily_news_path, exist_ok=True) +# 轻小说 +light_novel_path = path + '/image/lightnovel/' +os.makedirs(light_novel_path, exist_ok=True) +#yuc_wiki 动漫wiki +yuc_wiki_path = path + '/image/yuc_wiki/' +os.makedirs(yuc_wiki_path, exist_ok=True) +# 字体路径 +font_path = path + '/font/' +os.makedirs(font_path, exist_ok=True) +# 临时数据路径 +temp_path = path + '/temp/' +os.makedirs(temp_path, exist_ok=True) +# 日志路径 +log_path = path+'/log/' +os.makedirs(log_path, exist_ok=True) +# 视频路径 +video_path = path+'/video/' +os.makedirs(video_path, exist_ok=True) + + + +# # 语音路径 +# RECORD_PATH = Path() / "src" / "resources" / "record" +# # 文本路径 +# TEXT_PATH = Path() / "src" / "resources" / "text" +# # 数据路径 +# DATA_PATH = Path() / "src" / "data" +# # 网页模板路径 +# TEMPLATE_PATH = Path() / "src" / "resources" / "template" +# # 视频路径 +# VIDEO_PATH = Path() / "src" / "resources" / "videos" \ No newline at end of file diff --git a/src/configs/utils/__init__.py b/src/configs/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/plugins/bili_vid_search.py b/src/plugins/bili_vid_search.py new file mode 100644 index 0000000..5a0b3c3 --- /dev/null +++ b/src/plugins/bili_vid_search.py @@ -0,0 +1,117 @@ +# https://api.bilibili.com/x/web-interface/search/type?keyword=av28465342&search_type=video&page=1 + +import time +import nonebot.adapters.qq.exception +from nonebot import on_command +from nonebot.rule import to_me +from nonebot.adapters.qq import MessageSegment,MessageEvent, Message +import src.clover_videos.billibili.biliVideos as biliVideos +from src.configs.path_config import video_path + +bili_vid = on_command("B站搜索",rule=to_me(), priority=10, block=True) +@bili_vid.handle() +async def get_bili_vid_info(message: MessageEvent): + content = message.get_plaintext().replace("/B站搜索", "").strip() + response = biliVideos.get_video_info(content) + if response['code'] != 0: + bili_vid.finish(response['message']) + search_result = response['data']['result'] + + i = 0 + for vid_info in search_result: + i += 1 + if i >= 4: + break + pic = "https:" + str(vid_info['pic']) + # print(pic) + if vid_info['description'].strip() == "": + dis = "无" + else: + dis = vid_info['description'] + description = ("\n标题: " + str(vid_info['title']).replace('', "").replace('', "") + + "\nup主: " + vid_info['author'] + + "\n" + vid_info['bvid']) + msg = Message([ + MessageSegment.image(pic), + MessageSegment.text(description), + ]) + await bili_vid.send(msg) + time.sleep(0.5) + + await bili_vid.finish(f"展示{len(search_result)}条结果中的前3条。") + + +bili_bv_search = on_command("BV搜索", rule=to_me(), priority=10, block=True) +@bili_bv_search.handle() +async def get_video_file(message: MessageEvent): + keyword = message.get_plaintext().replace("/BV搜索", "").strip().split() + P_num, pages, vid_title, vid_author, vid_pic = biliVideos.get_video_pages_info(keyword[0]) + if len(keyword) == 1: + + if P_num > 1: + content = "\n标题:" + vid_title + "\nup主: " + vid_author + "\n该视频为多P播放:\n" + for page in pages: + content = content + "P" + str(page['page']) + ": " + page['part'] + "\n时长: " + str(page['duration']) + "s\n\n" + + content = content + "请选择您想播放的集数。\n决定好后麻烦回复 /BV搜索+BV号+序号 哦。\n" + await bili_bv_search.finish(content) + + elif P_num == 1: + + content = ("\n标题: " + vid_title + "\nup主: " + vid_author + "\n视频加载中~请稍后~~~") + msg = Message([ + MessageSegment.image(vid_pic), + MessageSegment.text(content), + ]) + await bili_bv_search.send(msg) + + cid = pages[0]['cid'] + video_url = biliVideos.get_video_file_url(keyword[0], cid) + # biliVideos.video_download(video_url, cid) + # biliVideos.transcode_video(f"./src/resources/videos/{cid}.mp4",f"./src/resources/videos/{cid}-o.mp4") + + try: + # await bili_bv_search.send(Message(MessageSegment.file_video(Path(video_path + f"/{cid}-o.mp4")))) + await bili_bv_search.send(MessageSegment.video(video_url)) + except nonebot.adapters.qq.exception.ActionFailed as e: + print("\033[32m" + str(time.strftime("%m-%d %H:%M:%S")) +"\033[0m [" + "\033[31;1mFAILED\033[0m" + "]" + "\033[31;1m nonebot.adapters.qq.exception.ActionFailed \033[0m" + str(e)) + await bili_bv_search.finish("发送失败惹,可能是视频过长,请尽量搜索1分钟以内的视频吧。") + + # biliVideos.delete_video(cid) + + elif len(keyword) >= 2: + + try: + page_num = int(keyword[1]) + except: + await bili_bv_search.finish("输入有误\n请确认是否为 /BV搜索+BV号+序号(数字) ") + + if page_num > len(pages): + page_num = len(pages) + elif page_num < 1: + page_num = 1 + + content = ("\n标题: " + vid_title + "\nup主: " + vid_author + "\n正在播放共" + str(P_num) + "P中的第" + str(page_num) + "P" + "\n视频加载中~请稍后~~~") + msg = Message([ + MessageSegment.image(vid_pic), + MessageSegment.text(content), + ]) + await bili_bv_search.send(msg) + + cid = pages[page_num - 1]['cid'] + video_url = biliVideos.get_video_file_url(keyword[0], cid) + # biliVideos.video_download(video_url, cid) + # biliVideos.transcode_video(VIDEO_PATH / f"{cid}.mp4", VIDEO_PATH / f"{cid}-o.mp4") + + try: + # await bili_bv_search.send(Message(MessageSegment.file_video(Path(VIDEO_PATH / f"{cid}.mp4")))) + await bili_bv_search.send(MessageSegment.video(video_url)) + except nonebot.adapters.qq.exception.ActionFailed as e: + print("\033[32m" + str(time.strftime("%m-%d %H:%M:%S")) + + "\033[0m [" + "\033[31;1mFAILED\033[0m" + "]" + + "\033[31;1m nonebot.adapters.qq.exception.ActionFailed \033[0m" + str(e)) + await bili_bv_search.finish("发送失败惹,可能是视频过长,请尽量搜索1分钟以内的视频吧。") + + # biliVideos.delete_video(cid) + + await bili_bv_search.finish() diff --git a/src/plugins/chat.py b/src/plugins/chat.py new file mode 100644 index 0000000..a4c5a96 --- /dev/null +++ b/src/plugins/chat.py @@ -0,0 +1,95 @@ +import re +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageEvent +from src.clover_sqlite.models.chat import ChatRole, GroupChatRole +from src.configs.api_config import admin_password + + +t1 = on_command("管理员注册", rule=to_me(), priority=10, block=True) +@t1.handle() +async def handle_function(message: MessageEvent): + if not hasattr(message, 'group_openid'): + await t1.finish("暂未在当前场景下开放此功能。") + + member_openid, group_openid = message.author.id, message.group_openid + password = message.get_plaintext().replace("/管理员注册", "").strip() + if password == admin_password: + result = await GroupChatRole.blind_admin([member_openid], group_openid) + await t1.finish(result) + else: + await t1.finish("管理员注册密码错误。") + + +t3 = on_command("开启ai",aliases={"关闭ai"},rule=to_me(),priority=10,block=True) +@t3.handle() +async def handle_function(message: MessageEvent): + + if not hasattr(message, 'group_openid'): + await t3.finish("暂未在当前场景下开放此功能。") + + member_openid, group_openid, content = message.author.id, message.group_openid, message.get_plaintext() + # 判断是否为管理员 + if not await GroupChatRole.get_admin_list(group_openid, member_openid): + await t3.finish("您没有权限使用此功能。") + else: + status = await GroupChatRole.is_on(group_openid) + if not status and content == "/开启ai": + await GroupChatRole.ai_switch(group_openid) + await t3.finish("成功开启语言模型对话功能。一起来聊天吧~") + elif status and content == "/开启ai": + await t3.finish("当前群已开启ai聊天。请勿重复开启") + elif status and content == "/关闭ai": + await GroupChatRole.ai_switch(group_openid) + await t3.finish("成功关闭语言模型对话功能。") + elif not status and content == "/关闭ai": + await t3.finish("当前群已关闭ai聊天,请勿重复关闭。") + + +tt = on_command("角色列表", rule=to_me(), priority=10, block=True) +@tt.handle() +async def handle_function(message: MessageEvent): + + if not hasattr(message, 'group_openid'): + await tt.finish("暂未在当前场景下开放此功能。") + + member_openid, group_openid = message.author.id, message.group_openid + if not await GroupChatRole.get_admin_list(group_openid, member_openid): + await tt.finish("您没有权限使用此功能。") + role_setting = await ChatRole.get_role_list() + if (role_setting is None) | (not role_setting): + await tt.finish("角色设定库为空,请添加角色以及设定") + else: + await tt.finish(str(role_setting)) + + +t2 = on_command("添加人设",aliases={"更新人设","删除人设","切换人设"},rule=to_me(),priority=10,block=True) +@t2.handle() +async def handle_function(message: MessageEvent): + + if not hasattr(message, 'group_openid'): + await t2.finish("暂未在当前场景下开放此功能。") + + member_openid, group_openid = message.author.id, message.group_openid + if not await GroupChatRole.get_admin_list(group_openid, member_openid): + await t2.finish("您没有权限使用此功能。") + value = message.get_plaintext().strip().split(" ") + action, role_name = value[0], value[1] + if action == "/删除人设": + result = await ChatRole.delete_role(role_name) + await t2.finish(result) + if action == "/切换人设": + result = await GroupChatRole.set_chat_role(group_openid,role_name) + await t2.finish(result) + if len(value[1])>10: + await t2.finish("角色名称过长,请重新输入") + if len(value) < 3: + await t2.finish("请输入角色名称和设定,格式为:命令 角色名称 角色设定") + role_setting = re.sub(r'[\n\\n\s"‘’]', '', ''.join(value[2:])) + if action == "/添加人设": + result = await ChatRole.insert_role_setting(role_name, role_setting) + await t2.finish(result) + if action == "/更新人设": + result = await ChatRole.update_role_setting(role_name, role_setting) + await t2.finish(result) + diff --git a/src/plugins/check.py b/src/plugins/check.py new file mode 100644 index 0000000..6e07697 --- /dev/null +++ b/src/plugins/check.py @@ -0,0 +1,86 @@ +import os +import random +from nonebot import on_message +from nonebot.rule import Rule, to_me +from nonebot.plugin import on_command, on_keyword +from nonebot.adapters.qq import Message, MessageEvent +from src.clover_openai import ai_chat +from src.clover_sqlite.models.chat import GroupChatRole +from src.clover_sqlite.models.user import UserList + +menu = ["/重启","/今日运势","/今日塔罗","/图","/日报","/点歌","/摸摸头","/群老婆","/今日老婆", "/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册", + "/待办", "/test","/天气","我喜欢你", "❤", "/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报", "/luxun","/鲁迅说", + "/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/新番观察"] + +send_menu = ["/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册", "/待办", "/test", "我喜欢你", "❤", "/menu"] + +async def check_value_in_menu(message: MessageEvent) -> bool: + value = message.get_plaintext().strip().split(" ") + if hasattr(message, "group_openid"): # 是否有属性group_openid,即是否为群聊消息 + group_id = message.group_openid + else: + group_id = "C2C" # 非群聊消息,存为c2c + #缓存用户id + await UserList.insert_user(message.author.id,group_id) + if value[0] in menu: + return False + else: + return True + + +check = on_message(rule=to_me() & Rule(check_value_in_menu) ,block=True, priority=10) +@check.handle() +async def handle_function(message: MessageEvent): + + if hasattr(message, "group_openid"): + group_openid = message.group_openid + else: + group_openid = "C2C" + + member_openid, content = message.author.id, message.get_plaintext() + status = await GroupChatRole.is_on(group_openid) + if status: + msg = await ai_chat.deepseek_chat(group_openid,content) + await check.finish(msg) + else: + await check.finish(message=Message(random.choice(text_list))) + +text_list = [ + "是什么呢?猫猫没有识别到,喵~"+"\n"+"(๑>ڡ<)☆ 给个准信,别让我瞎猜", + "是想让我干嘛呢?猫猫一头雾水,喵~" + "\n" + "(๑•̀ㅂ•́)و✧ 直接跟我说,别这么含蓄,喵~", + "是啥意思呀?猫猫完全没搞懂,喵~" + "\n" + "(๑・.・๑) 别折腾我啦,说明白,喵~", + "是特殊信号?猫猫听不懂,喵~" + "\n" + "(๑・̀︶・́)و 下个明确指令,喵~", + "难道是新指令?猫猫一脸茫然,喵~" + "\n" + "(๑>ڡ<)☆ 说详细点,别这么隐晦,喵~", +] + +get_menu = on_command("menu", rule=to_me(), priority=10, block=True) +@get_menu.handle() +async def send_menu_list(): + content = "\n" + for command in send_menu: + content += command + "\n" + await get_menu.finish(content) + +restart = on_command("重启", rule=to_me(), priority=10, block=True) +@restart.handle() +async def handle_function(message: MessageEvent): + + member_openid, group_openid = message.author.id, message.group_openid + if not await GroupChatRole.get_admin_list(group_openid, member_openid): + await restart.finish("您没有权限使用此功能。") + + return_code = os.system("python ./update_remote_code.py") + if return_code == 0: + await restart.finish("重启成功,请10s后再试。") + else: + await restart.finish("重启失败") + +love = on_keyword({"我喜欢你", "❤"}, rule=to_me(), priority=2, block=False) +@love.handle() +async def spread_love(): + await love.finish("我也喜欢你。") + +test = on_command("test", rule=to_me(), priority=10, block=True) +@test.handle() +async def bot_on_ready(): + await test.finish("\nBoost & Magnum, ready fight!!!") diff --git a/src/plugins/cloud_music.py b/src/plugins/cloud_music.py new file mode 100644 index 0000000..2561691 --- /dev/null +++ b/src/plugins/cloud_music.py @@ -0,0 +1,72 @@ +import pickle +import time +from pathlib import Path +from nonebot import on_command +from nonebot.rule import to_me +from nonebot.adapters.qq import MessageSegment,MessageEvent +from src.clover_music.cloud_music.cloud_music import * + +music = on_command("点歌", rule=to_me(), priority=10, block=True) +@music.handle() +async def handle_function(msg: MessageEvent): + keyword = msg.get_plaintext().replace("/点歌", "").strip(" ") + + if keyword == "": + await music.finish("\n请输入“/点歌+歌曲名”喔🎶") + + #获取登录信息 可以获取更换高音质 + session = requests.session() + if not os.path.exists('cloud_music_cookies.cookie'): + with open('cloud_music_cookies.cookie', 'wb') as f: + pickle.dump(session.cookies, f) + # 读取 cookie + session.cookies = pickle.load(open('cloud_music_cookies.cookie', 'rb')) + session, status = netease_cloud_music_is_login(session) + if not status: + await music.send("登录失效,请联系管理员进行登录") + unikey = get_qr_key(session) + path = create_qr_code(unikey) + + """是否要发送到QQ上面登录 """ + # await clover_music.send(MessageSegment.file_image(Path(path))) + """是否要发送到QQ上面登录 """ + + while True: + code = check_qr_code(unikey, session) + if '801' in str(code): + print('二维码未失效,请扫码!') + elif '802' in str(code): + print('已扫码,请确认!') + elif '803' in str(code): + print('已确认,登入成功!') + break + else: + print('其他:', code) + time.sleep(2) + with open('cloud_music_cookies.cookie', 'wb') as f: + pickle.dump(session.cookies, f) + + #搜索歌曲 + song_id,song_name,singer,song_url = netease_music_search(keyword,session) + song_name = str(song_name).replace(".", "·").replace("/", "、") + if song_id is None: + await music.finish("\n没有找到歌曲,或检索到的歌曲均为付费喔qwq\n这绝对不是我的错,绝对不是!") + else: + await music.send(MessageSegment.text(f" 来源:网易云音乐\n歌曲:{song_name} - {singer}\n请稍等喔🎵")) + #返回转换后的歌曲路径 + output_silk_path = netease_music_download(song_id, song_name, singer,session) + + if output_silk_path == -1: + await music.send("歌曲音频获取失败:登录信息失效。") + elif output_silk_path is None: + await music.send("歌曲音频获取失败了Σヽ(゚Д ゚; )ノ,请重试。") + else: + await music.send(MessageSegment.file_audio(Path(output_silk_path))) + + #删除临时文件 + netease_music_delete() + await music.finish() + + + + diff --git a/src/plugins/codeforces.py b/src/plugins/codeforces.py new file mode 100644 index 0000000..9ae8ac2 --- /dev/null +++ b/src/plugins/codeforces.py @@ -0,0 +1,56 @@ +import requests +from nonebot.plugin import on_command +from nonebot.rule import to_me +from nonebot.adapters.qq import Message, MessageEvent, MessageSegment +from pathlib import Path +from src.configs.path_config import path + +cf_query = on_command("cf", rule=to_me(), priority=10, block=True) +@cf_query.handle() +async def get_cf_rounds(): + await cf_query.send("正在为您整理近期比赛信息哦~\n请稍等💭💡🎈") + try: + result = requests.get('https://codeforces.com/api/contest.list?gym=false').json() + except BaseException: + await cf_query.finish("API请求失败,这绝对不是咱的错,绝对不是!") + all_matches = "" + for matches in result['result']: + phase = get_match_phase(matches["phase"]) + one_match = ("\n比赛:" + str(matches["name"]) + "\n状态:" + phase + "\n时长:" + str(int(matches["durationSeconds"]) / 3600) +"h\n") + all_matches = "".join([all_matches, one_match]) + if phase == "未开始": + until_start_time_min = 0 - int(matches["relativeTimeSeconds"]) / 60 + until_start = get_until_start_time(until_start_time_min) + all_matches = "".join([all_matches, until_start]) + if matches["phase"] == "FINISHED": + break + + cf_image_path = path + "/image/codeforces/cfContestQR.png" + msg = Message([ + MessageSegment.file_image(Path(cf_image_path)), + MessageSegment.text(all_matches), + ]) + + await cf_query.finish(msg) + + +def get_match_phase(phase): + phase_map = { + "BEFORE": "未开始", + "FINISHED": "已结束", + "CODING": "进行中", + "PENDING_SYSTEM_TEST": "等待判题", + "SYSTEM_TEST": "判题中", + } + return phase_map.get(phase, "未知") + + +def get_until_start_time(until_start_time_min): + if until_start_time_min <= 180: + return "距开始:" + str(int(until_start_time_min)) + "min\n" + elif 180 < until_start_time_min <= 1440: + return "距开始:" + str(int(until_start_time_min / 60)) + "h\n" + elif until_start_time_min > 1440: + return "距开始:" + str(int(until_start_time_min / 60 / 24)) + "days\n" + else: + return "距开始:未知\n" diff --git a/src/plugins/daily_report.py b/src/plugins/daily_report.py new file mode 100644 index 0000000..b6d05d2 --- /dev/null +++ b/src/plugins/daily_report.py @@ -0,0 +1,20 @@ +from datetime import datetime +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageSegment +from src.clover_report.data_source import Report +from src.configs.path_config import daily_news_path +import os + + +daily_report = on_command("日报", rule=to_me(), priority=10, block=True) +@daily_report.handle() +async def handle_function(): + now = datetime.now() + file = Path() / daily_news_path / f"{now.date()}.png" + if not os.path.exists(file): + await daily_report.send("您是今天第一个查看日报的哦,来看看世界上都发生了些什么吧💫\nCrunching the latest news, just for you. Hang tight…") + await Report.get_report_image() + now = datetime.now().date() + await daily_report.finish(MessageSegment.file_image(Path(daily_news_path+f"{now}.png"))) diff --git a/src/plugins/fortune.py b/src/plugins/fortune.py new file mode 100644 index 0000000..0476f21 --- /dev/null +++ b/src/plugins/fortune.py @@ -0,0 +1,57 @@ +# 引入sqlalchemy依赖 +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import Message, MessageEvent, MessageSegment,exception +from src.clover_image.get_image import get_image_names +from src.clover_sqlite.models.fortune import QrFortune +from src.clover_sqlite.models.tarot import MajorArcana +import time + +fortune_by_sqlite = on_command("今日运势", rule=to_me(), priority=10, block=True) +@fortune_by_sqlite.handle() +async def get_today_fortune(message: MessageEvent): + + local_image_path = get_image_names() + result = await QrFortune.get_fortune(message.get_user_id()) + + content = ("\n" + "您的今日运势为:" + "\n" + + result.fortune_summary + "\n" + + result.lucky_star + "\n" + + "签文:" + result.sign_text + "\n" + + "————————————" + "\n" + + "解签:" + result.un_sign_text) + + msg = Message([ + MessageSegment.file_image(Path(local_image_path)), + MessageSegment.text(content), + ]) + try: + await fortune_by_sqlite.finish(msg) + except exception.ActionFailed as e: + print("\033[32m" + str(time.strftime("%m-%d %H:%M:%S")) + + "\033[0m [" + "\033[31;1mFAILED\033[0m" + "]" + + "\033[31;1m nonebot.adapters.qq.exception.ActionFailed \033[0m" + str(e)) + await fortune_by_sqlite.finish("您的今日运势被外星人抢走啦,请重试。这绝对不是咱的错,绝对不是!") + + +tarot = on_command("今日塔罗", rule=to_me(), priority=10, block=True) +@tarot.handle() +async def get_tarot(message: MessageEvent): + result = await MajorArcana.tarotChoice(message.get_user_id()) + + content = ("\n" + result.ints + "\n" + + result.name + "\n" + + "含义:" + result.meaning) + + msg = Message([ + MessageSegment.file_image(Path(result.image)), + MessageSegment.text(content), + ]) + try: + await tarot.finish(msg) + except exception.ActionFailed as e: + print("\033[32m" + str(time.strftime("%m-%d %H:%M:%S")) + + "\033[0m [" + "\033[31;1mFAILED\033[0m" + "]" + + "\033[31;1m nonebot.adapters.qq.exception.ActionFailed \033[0m" + str(e)) + await tarot.finish("您的塔罗牌被未来人抢走啦,请重试。这绝对不是咱的错,绝对不是!") diff --git a/src/plugins/good_bad_news.py b/src/plugins/good_bad_news.py new file mode 100644 index 0000000..ae8cc4b --- /dev/null +++ b/src/plugins/good_bad_news.py @@ -0,0 +1,64 @@ +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import Message, MessageEvent, MessageSegment, exception +import urllib.parse +import requests +import time +import httpx +from src.clover_image.add_text_to_image import add_text_to_image +from src.clover_image.delete_file import delete_file +from src.configs.path_config import font_path,good_bad,temp_path + +# good_news = on_command("喜报", rule=to_me(), priority=10, block=True, aliases={"悲报"}) +# @good_news.handle() +# async def good_news_img(message: MessageEvent): +# if message.get_plaintext().startswith("/喜报"): +# content = message.get_plaintext().replace("/喜报", "").strip() +# url = "https://cdn.uuuix.com/api/v1/xbs/xb.php?" +# else: +# content = message.get_plaintext().replace("/悲报", "").strip() +# url = "https://cdn.uuuix.com/api/v1/xbs/biob.php?" +# +# params = { +# 'msg': content +# } +# +# await good_news.send("图片绘制中,请稍后~\n技术支持: JianDan大佬\nwww·uuuix·com") +# +# query = urllib.parse.urlencode(params) +# response = requests.get(url + query).json() +# +# if response['code'] != 1: +# await good_news.finish("请输入 /喜(悲)报+内容 哦。") +# +# img_url = response['url'] + # try: + # await good_news.finish(MessageSegment.clover_image(img_url)) + # except BaseException: + # await good_news.finish("出错啦,请重试。") + + +good_news = on_command("喜报", rule=to_me(), priority=10, block=True, aliases={"悲报"}) +@good_news.handle() +async def function(message: MessageEvent): + value = message.get_plaintext().split(" ") + filename = "" + if len(value) < 2 or len(value) > 2: + await good_news.finish("请输入 正确的格式哦~ /喜报+内容 或者 /悲报+内容") + keyword, content = value[0], value[1] + if value[1] == "": + await good_news.finish("请输入 正确的格式哦~ /喜报+内容 或者 /悲报+内容") + if keyword == "/喜报": + filename = "good_news.png" + await add_text_to_image(image_path=good_bad + filename, output_path=temp_path + filename, content=content, + font_path=font_path + "微软雅黑.ttc", font_size=72, text_color=(255, 0, 0),text_position="center", + position="center") + await good_news.finish(MessageSegment.file_image(Path(temp_path + filename))) + elif keyword == "/悲报": + filename = "bad_news.png" + await add_text_to_image(image_path=good_bad + filename, output_path=temp_path + filename, content=content, + font_path=font_path + "微软雅黑.ttc", font_size=72, text_color=(128, 128, 128),text_position="center", + position="center") + await good_news.finish(MessageSegment.file_image(Path(temp_path+filename))) + await delete_file(temp_path + filename) \ No newline at end of file diff --git a/src/plugins/image.py b/src/plugins/image.py new file mode 100644 index 0000000..f353144 --- /dev/null +++ b/src/plugins/image.py @@ -0,0 +1,27 @@ +import random +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageSegment,MessageEvent +from src.clover_image.get_image import get_image_names +from src.clover_image.download_image import download_image +from src.configs.path_config import temp_path + + +image = on_command("图", rule=to_me(), priority=10, block=True) +@image.handle() +async def handle_function(): + + local_image_path = get_image_names() + await image.finish(MessageSegment.file_image(Path(local_image_path))) + + +image = on_command("/搜图", rule=to_me(), priority=10, block=True) +@image.handle() +async def handle_function(message: MessageEvent): + + filename = str(message.get_user_id()) + str(random.randint(0, 10000)) + ".jpg" + image_ptah = temp_path + filename + + download_image(message.attachments[0].url, image_ptah) + await image.finish(MessageSegment.file_image(Path(image_ptah))) \ No newline at end of file diff --git a/src/plugins/light_novel.py b/src/plugins/light_novel.py new file mode 100644 index 0000000..6965bd9 --- /dev/null +++ b/src/plugins/light_novel.py @@ -0,0 +1,20 @@ +from datetime import datetime +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageSegment +from src.clover_lightnovel.html_to_img import get_ln_image +from src.configs.path_config import light_novel_path +import os + + +light_novel = on_command("轻小说", rule=to_me(), priority=10, block=True) +@light_novel.handle() +async def get_ln(): + now = datetime.now() + file = Path() / light_novel_path / f"{now.date()}.png" + if not os.path.exists(file): + await light_novel.send("正在为您整理最新轻小说咨询哦,请稍等🥳") + await get_ln_image() + now = datetime.now().date() + await light_novel.finish(MessageSegment.file_image(Path(light_novel_path+f"{now}.png"))) \ No newline at end of file diff --git a/src/plugins/nai_loong.py b/src/plugins/nai_loong.py new file mode 100644 index 0000000..30b02a3 --- /dev/null +++ b/src/plugins/nai_loong.py @@ -0,0 +1,18 @@ +import random +from nonebot.rule import to_me +from nonebot.plugin import on_keyword +from nonebot.adapters.qq import Message + + +nai_loong = on_keyword({"奶龙"}, rule=to_me(), priority=1, block=True) +@nai_loong.handle() +async def not_nai_loong(): + await nai_loong.finish(message=Message(random.choice(text_list_nailoong))) + +text_list_nailoong = [ + "我是?你是?😨", + "你才是奶龙😡", + "你是奶龙?🤔我是奶龙?😨你才是奶龙!😱", + "今夜星光闪闪✨️我爱你的心满满🤩", + "唐", +] \ No newline at end of file diff --git a/src/plugins/platform.py b/src/plugins/platform.py new file mode 100644 index 0000000..5eeba4a --- /dev/null +++ b/src/plugins/platform.py @@ -0,0 +1,42 @@ +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import Message, MessageSegment +import platform +import psutil +import time + + +repository = on_command("repo", rule=to_me(), priority=10, block=True) +@repository.handle() +async def github_repo(): + + content = "三叶草bot仓库地址\n一起来搭个机器人吧😆" + msg = Message([ + MessageSegment.file_image(Path("src/resources/image/github_repo/SanYeCao-Nonebot3.png")), + MessageSegment.text(content), + ]) + await repository.finish(msg) + +platform_info = on_command("info", rule=to_me(), priority=10, block=True) +@platform_info.handle() +async def get_platform_info(): + # 获取操作系统名称 + os_name = platform.system() + os_version = platform.version() + processor_name = platform.processor() + processor_architecture = platform.architecture() + python_version = platform.python_version() + memory = psutil.virtual_memory().total + memory_usage = psutil.virtual_memory().percent + cpu_usage = psutil.cpu_percent() + + content = ("\n[操作系统]: " + os_name + "\n[系统版本]: " + os_version + "\n[开机时长]: " + str(format((time.time() - psutil.boot_time()) / 3600, ".1f")) + "h" + + "\n[服务器时间]: \n" + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + + "\n\n[CPU架构]: " + processor_architecture[0] + ", " + processor_architecture[1] + + "\n[CPU占用]: " + str(cpu_usage) + "%" + + "\n\n[物理内存]: " + str(format(memory / (1024 ** 3), ".1f")) + "GB" + + "\n[内存占用]: " + str(memory_usage) + "%" + "\n\n[Python版本]: " + python_version + + "\n\n[Bot源码]: 请发送 /repo \n[联系我们]: cloverta@petalmail·com") + await platform_info.finish(content) \ No newline at end of file diff --git a/src/plugins/test/test.py b/src/plugins/test/test.py new file mode 100644 index 0000000..46aa7ee --- /dev/null +++ b/src/plugins/test/test.py @@ -0,0 +1,75 @@ +import random + +# 中文数字映射 +chinese_numbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'] + + +# 生成对称且带有一个不同字符的矩阵 +def generate_matrix(rows=9, cols=9): + base_char = '辏' + special_char = '鞅' + matrix = [[base_char] * cols for _ in range(rows)] + # 确保矩阵对称 + for i in range(rows): + for j in range(i, cols): + matrix[j][i] = matrix[i][j] + # 随机选择一个位置放置不同字符 + diff_row = random.randint(0, rows - 1) + diff_col = random.randint(0, cols - 1) + matrix[diff_row][diff_col] = special_char + # 保持对称 + matrix[diff_col][diff_row] = special_char + return matrix + + +# 打印矩阵,使用中文数字表示行号和列号 +def print_matrix(matrix): + col_num = len(matrix[0]) + # 打印列数头部 + col_header = " " + " ".join([chinese_numbers[i + 1] for i in range(col_num)]) + print(f"{chinese_numbers[0]} |{col_header}") + # 打印分隔线 + print(" " + "——" * (len(col_header))) + for i, row in enumerate(matrix, start=1): + row_str = " ".join(row) + print(f"{chinese_numbers[i]} | {row_str}") + + +# 主游戏函数 +def play_game(): + matrix = generate_matrix() + print("矩阵:") + print_matrix(matrix) + + while True: + try: + row_input = input("请输入不同字符所在的行(如 一),输入 '退出' 结束游戏: ") + if row_input == '退出': + print("游戏结束。") + break + col_input = input("请输入不同字符所在的列(如 一): ") + + row_answer = chinese_numbers.index(row_input) - 1 + col_answer = chinese_numbers.index(col_input) - 1 + + # 找出实际不同字符的位置 + for i in range(len(matrix)): + for j in range(len(matrix[0])): + if matrix[i][j] != '辏': + correct_row = i + correct_col = j + break + + if row_answer == correct_row and col_answer == correct_col: + print("恭喜你,回答正确!") + break + else: + print("回答错误,请再试一次。") + except ValueError: + print("输入无效,请输入正确的中文数字或 '退出'。") + + +if __name__ == "__main__": + play_game() + + diff --git a/src/plugins/to_do.py b/src/plugins/to_do.py new file mode 100644 index 0000000..9787b4d --- /dev/null +++ b/src/plugins/to_do.py @@ -0,0 +1,51 @@ +from nonebot.adapters.qq import MessageEvent +from nonebot.plugin import on_command +from nonebot.rule import to_me +from src.clover_sqlite.models.to_do import ToDoList + +get_todo_list = on_command("待办查询", rule=to_me(), priority=10, block=True, aliases={"代办", "daiban"}) +@get_todo_list.handle() +async def show_todo_list(message: MessageEvent): + """ + 查询用户所有的待办 + + :param message: + :return: + """ + member_openid = message.get_user_id() + result = await ToDoList.get_todo_list(member_openid) + if not result: + await get_todo_list.finish("\n您还未创建待办\n快使用 /新建待办 创建一份吧") + + todo_list = "\n\n".join([f"{i + 1}. {content}" for i, content in enumerate(result)]) + await get_todo_list.finish(f"您的待办有如下哦:⭐\n\n{todo_list}") + + +insert_todo = on_command("新建待办", rule=to_me(), priority=10, block=True) +@insert_todo.handle() +async def insert_todo_list(message: MessageEvent): + member_openid = message.get_user_id() + content = message.get_plaintext().replace("/新建待办", "").strip(" ") + success = await ToDoList.insert_todo_list(member_openid, content) + if success: + await insert_todo.finish("成功添加待办,今后也要加油哦(ง •_•)ง") + else: + await insert_todo.finish("\n请输入 /新建待办+待办内容 哦") + + +delete_todo = on_command("删除待办", rule=to_me(), priority=10, block=True) +@delete_todo.handle() +async def del_todo(message: MessageEvent): + member_openid = message.get_user_id() + del_line_str = message.get_plaintext().replace("/删除待办", "").strip(" ") + try: + del_line_num = int(del_line_str) + except BaseException: + await delete_todo.finish("请检查您的输入是否正确。\n请输入 /删除待办+数字 哦。") + result = await ToDoList.delete_user_todo(member_openid, del_line_num) + if result == -1: + await delete_todo.finish("您还未创建过待办哦。") + elif result == 0: + await delete_todo.finish("成功删除第" + str(del_line_num) + "条待办。") + elif result == 1: + await delete_todo.finish("没有找到这条待办哦,请检查您的输入是否正确.") diff --git a/src/plugins/today_wife.py b/src/plugins/today_wife.py new file mode 100644 index 0000000..d79023b --- /dev/null +++ b/src/plugins/today_wife.py @@ -0,0 +1,39 @@ +from pathlib import Path +from nonebot.adapters.qq import Message, MessageEvent +from nonebot.adapters.qq import MessageSegment +from nonebot.plugin import on_command +from nonebot.rule import to_me +from src.clover_image.qq_image import download_qq_image,qq_image_delete +from src.clover_sqlite.models.user import UserList + +today_group_wife = on_command("群老婆", rule=to_me(), priority=10, block=True) +@today_group_wife.handle() +async def handle_function(message: MessageEvent): + member_openid = message.get_user_id() + + user_id = await UserList.get_user_id(member_openid,message.group_id) + if user_id is None: + await today_group_wife.finish("潜在老婆太少了,快请群友多多使用吧") + local_image_path = download_qq_image(user_id) + msg = Message([ + MessageSegment.text("您的今日群老婆"), + MessageSegment.file_image(Path(local_image_path)), + ]) + qq_image_delete() + await today_group_wife.finish(msg) + + +today_wife = on_command("今日老婆", rule=to_me(), priority=10, block=True) +@today_wife.handle() +async def handle_function(message: MessageEvent): + member_openid = message.get_user_id() + + local_image_path = download_qq_image(member_openid) + msg = Message([ + MessageSegment.file_image(Path(local_image_path)), + ]) + + qq_image_delete() + await today_wife.finish(msg) + + diff --git a/src/plugins/touch.py b/src/plugins/touch.py new file mode 100644 index 0000000..25cf65e --- /dev/null +++ b/src/plugins/touch.py @@ -0,0 +1,28 @@ +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import Message, MessageEvent, MessageSegment +from src.clover_sqlite.models.touch import QrTouch, QrTouchLog +from src.clover_image.qq_image import download_qq_image_by_account, qq_image_delete +from src.clover_image.rua import rua + +to = on_command("摸摸头", rule=to_me(), priority=10, block=True) +@to.handle() +async def handle_touch(message: MessageEvent): + member_openid = message.get_user_id() + num = await QrTouchLog.touch_count(member_openid) + if num > 10: + await to.finish("你今天已经摸了太多次了,请明天再吧!") + q = QrTouch() + q.touch_status = 1 + if num > 5: + result = await QrTouch.touch(1) + else: + result = await QrTouch.touch(0) + q.reply_touch_content = result.reply_touch_content + await QrTouchLog.insert_touch_log(q, member_openid) + local_gif = rua(download_qq_image_by_account(None)).add_gif() + msg = Message([MessageSegment.file_image(Path(local_gif)), + MessageSegment.text(result.reply_touch_content),]) + qq_image_delete() + await to.finish(msg) diff --git a/src/plugins/weather.py b/src/plugins/weather.py new file mode 100644 index 0000000..a7152a6 --- /dev/null +++ b/src/plugins/weather.py @@ -0,0 +1,60 @@ +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters import Message +from nonebot.params import CommandArg + +weather = on_command("天气", rule=to_me(), aliases={"weather", "查天气"}, priority=10, block=True) + +@weather.handle() +async def handle_function(args: Message = CommandArg()): + + # 提取参数纯文本作为地名,并判断是否有效 + if location := args.extract_plain_text(): + # 调用天气查询API获取天气数据 + weather_data = format_weather(location) + await weather.finish(weather_data) + else: + await weather.finish("请输入地名") + + +import requests + +def get_weather(location): + # 设置请求的URL和参数 + url = f'https://apis.juhe.cn/simpleWeather/query?key=50a3bd415158e186903d6e6994157589&city={location.rstrip("市").rstrip("县").rstrip("区")}' + # 发送GET请求 + response = requests.get(url) + # 检查请求是否成功 + if response.status_code == 200: + # 解析返回的JSON数据 + data = response.json() + + # 检查是否查询成功 + if data['reason'] == '查询成功!' or data['reason'] == '查询成功': + # 返回天气数据 + return data['result'] + else: + return {"error": "查询失败: " + data['reason']} + else: + return {"error": "请求失败,状态码: " + str(response.status_code)} + + +# 调用函数并处理返回的天气数据 +def format_weather(location): + # 假设这里你已经有了城市的URL编码,这里用'%E9%87%8D%E5%BA%86'作为示例 + city_encoded = location # 重庆的URL编码 + weather_data = get_weather(city_encoded) + + # 检查是否返回了错误 + if 'error' in weather_data: + return weather_data['error'] + else: + # 实时天气 + realtime_weather = weather_data['realtime'] + result = "\n" + location.rstrip("市").rstrip("县").rstrip("区") + f"实时天气:" + "\n" + f"{realtime_weather['info']}, 温度: {realtime_weather['temperature']}℃, 湿度: {realtime_weather['humidity']}%, 风向: {realtime_weather['direct']}, 风力: {realtime_weather['power']}级, AQI: {realtime_weather['aqi']}" + # 未来几天的天气 + result = result + "\n" + "未来几天的天气:🌤⛈️☔️" + for day in weather_data['future']: + result = result + "\n" + f"日期: {day['date']}, 天气: {day['weather']}, 温度: {day['temperature']}, 风向: {day['direct']}" + return result + diff --git a/src/plugins/who_say.py b/src/plugins/who_say.py new file mode 100644 index 0000000..084764d --- /dev/null +++ b/src/plugins/who_say.py @@ -0,0 +1,26 @@ +import random +from pathlib import Path +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageEvent, MessageSegment +from src.clover_image.add_text_to_image import add_text_to_image +from src.clover_image.delete_file import delete_file +from src.configs.path_config import who_say_path,font_path,temp_path + + +luxun = on_command("luxun", aliases={"鲁迅说"}, rule=None) +@luxun.handle() +async def handle(message: MessageEvent): + + filename = str(message.get_user_id()) + str(random.randint(0, 10000)) + ".jpg" + value = message.get_plaintext().split(" ") + keyword, content = value[0], value[1] + if len(value) < 2 or len(value) > 2 or value[1] == "": + await luxun.finish("你让鲁迅说点啥?格式不对自己捋一捋吧~") + if len(content) >= 24: + await luxun.finish("太长了, 鲁迅说不完! 24字以内~") + else: + await add_text_to_image(image_path=who_say_path + "luxun.jpg", output_path=temp_path + filename, content=" "+content+" —鲁迅", + font_path=font_path + "华文行楷.TTF", font_size=28, text_color=(255, 255, 255),text_position="left", + position="bottom left corner 9/10") + await luxun.send(MessageSegment.file_image(Path(temp_path + filename))) + await delete_file(temp_path + filename) \ No newline at end of file diff --git a/src/plugins/yuc_wiki.py b/src/plugins/yuc_wiki.py new file mode 100644 index 0000000..062f16a --- /dev/null +++ b/src/plugins/yuc_wiki.py @@ -0,0 +1,14 @@ +from pathlib import Path +from nonebot.rule import to_me +from nonebot.plugin import on_command +from nonebot.adapters.qq import MessageSegment,MessageEvent +from src.clover_yuc_wiki.yuc_wiki import get_yuc_wiki + + + +yuc_wiki = on_command("本季新番",aliases={'新番观察'} ,rule=to_me(), priority=10, block=True) +@yuc_wiki.handle() +async def handle_function(message: MessageEvent): + keyword = message.get_plaintext().replace("/", "").strip(" ") + yuc_wiki_image = await get_yuc_wiki(keyword) + await yuc_wiki.finish(MessageSegment.file_image(Path(yuc_wiki_image))) diff --git a/src/resources/font/华文新魏.TTF b/src/resources/font/华文新魏.TTF new file mode 100644 index 0000000..afe13f4 Binary files /dev/null and b/src/resources/font/华文新魏.TTF differ diff --git a/src/resources/font/华文楷体.TTF b/src/resources/font/华文楷体.TTF new file mode 100644 index 0000000..5044116 Binary files /dev/null and b/src/resources/font/华文楷体.TTF differ diff --git a/src/resources/font/华文行楷.TTF b/src/resources/font/华文行楷.TTF new file mode 100644 index 0000000..53439a2 Binary files /dev/null and b/src/resources/font/华文行楷.TTF differ diff --git a/src/resources/font/微软雅黑.ttc b/src/resources/font/微软雅黑.ttc new file mode 100644 index 0000000..ea174b2 Binary files /dev/null and b/src/resources/font/微软雅黑.ttc differ diff --git a/src/resources/image/MaoYuNa/001.png b/src/resources/image/MaoYuNa/001.png new file mode 100644 index 0000000..e38a3d8 Binary files /dev/null and b/src/resources/image/MaoYuNa/001.png differ diff --git a/src/resources/image/MaoYuNa/002.png b/src/resources/image/MaoYuNa/002.png new file mode 100644 index 0000000..52970cc Binary files /dev/null and b/src/resources/image/MaoYuNa/002.png differ diff --git a/src/resources/image/MaoYuNa/003.png b/src/resources/image/MaoYuNa/003.png new file mode 100644 index 0000000..9231a83 Binary files /dev/null and b/src/resources/image/MaoYuNa/003.png differ diff --git a/src/resources/image/MaoYuNa/005.png b/src/resources/image/MaoYuNa/005.png new file mode 100644 index 0000000..98e4d29 Binary files /dev/null and b/src/resources/image/MaoYuNa/005.png differ diff --git a/src/resources/image/MaoYuNa/006.png b/src/resources/image/MaoYuNa/006.png new file mode 100644 index 0000000..ca818cd Binary files /dev/null and b/src/resources/image/MaoYuNa/006.png differ diff --git a/src/resources/image/MaoYuNa/007.png b/src/resources/image/MaoYuNa/007.png new file mode 100644 index 0000000..dd08f68 Binary files /dev/null and b/src/resources/image/MaoYuNa/007.png differ diff --git a/src/resources/image/MaoYuNa/008.png b/src/resources/image/MaoYuNa/008.png new file mode 100644 index 0000000..8601f32 Binary files /dev/null and b/src/resources/image/MaoYuNa/008.png differ diff --git a/src/resources/image/MaoYuNa/009.png b/src/resources/image/MaoYuNa/009.png new file mode 100644 index 0000000..ea00c0c Binary files /dev/null and b/src/resources/image/MaoYuNa/009.png differ diff --git a/src/resources/image/MaoYuNa/010.png b/src/resources/image/MaoYuNa/010.png new file mode 100644 index 0000000..36a0ff1 Binary files /dev/null and b/src/resources/image/MaoYuNa/010.png differ diff --git a/src/resources/image/MaoYuNa/011.png b/src/resources/image/MaoYuNa/011.png new file mode 100644 index 0000000..c329e0b Binary files /dev/null and b/src/resources/image/MaoYuNa/011.png differ diff --git a/src/resources/image/MaoYuNa/012.png b/src/resources/image/MaoYuNa/012.png new file mode 100644 index 0000000..a44b93e Binary files /dev/null and b/src/resources/image/MaoYuNa/012.png differ diff --git a/src/resources/image/MaoYuNa/013.png b/src/resources/image/MaoYuNa/013.png new file mode 100644 index 0000000..460696b Binary files /dev/null and b/src/resources/image/MaoYuNa/013.png differ diff --git a/src/resources/image/MaoYuNa/014.png b/src/resources/image/MaoYuNa/014.png new file mode 100644 index 0000000..7e8326a Binary files /dev/null and b/src/resources/image/MaoYuNa/014.png differ diff --git a/src/resources/image/MaoYuNa/015.png b/src/resources/image/MaoYuNa/015.png new file mode 100644 index 0000000..1e00e36 Binary files /dev/null and b/src/resources/image/MaoYuNa/015.png differ diff --git a/src/resources/image/MaoYuNa/016.png b/src/resources/image/MaoYuNa/016.png new file mode 100644 index 0000000..89162f3 Binary files /dev/null and b/src/resources/image/MaoYuNa/016.png differ diff --git a/src/resources/image/MaoYuNa/017.png b/src/resources/image/MaoYuNa/017.png new file mode 100644 index 0000000..684260d Binary files /dev/null and b/src/resources/image/MaoYuNa/017.png differ diff --git a/src/resources/image/MaoYuNa/018.png b/src/resources/image/MaoYuNa/018.png new file mode 100644 index 0000000..46211ee Binary files /dev/null and b/src/resources/image/MaoYuNa/018.png differ diff --git a/src/resources/image/MaoYuNa/019.png b/src/resources/image/MaoYuNa/019.png new file mode 100644 index 0000000..5b8a6c3 Binary files /dev/null and b/src/resources/image/MaoYuNa/019.png differ diff --git a/src/resources/image/MaoYuNa/020.png b/src/resources/image/MaoYuNa/020.png new file mode 100644 index 0000000..df39055 Binary files /dev/null and b/src/resources/image/MaoYuNa/020.png differ diff --git a/src/resources/image/MaoYuNa/021.png b/src/resources/image/MaoYuNa/021.png new file mode 100644 index 0000000..1b1eb7f Binary files /dev/null and b/src/resources/image/MaoYuNa/021.png differ diff --git a/src/resources/image/MaoYuNa/022.png b/src/resources/image/MaoYuNa/022.png new file mode 100644 index 0000000..be7d939 Binary files /dev/null and b/src/resources/image/MaoYuNa/022.png differ diff --git a/src/resources/image/MaoYuNa/023.png b/src/resources/image/MaoYuNa/023.png new file mode 100644 index 0000000..157bb81 Binary files /dev/null and b/src/resources/image/MaoYuNa/023.png differ diff --git a/src/resources/image/MaoYuNa/024.png b/src/resources/image/MaoYuNa/024.png new file mode 100644 index 0000000..428327d Binary files /dev/null and b/src/resources/image/MaoYuNa/024.png differ diff --git a/src/resources/image/MaoYuNa/025.png b/src/resources/image/MaoYuNa/025.png new file mode 100644 index 0000000..1bb308d Binary files /dev/null and b/src/resources/image/MaoYuNa/025.png differ diff --git a/src/resources/image/MaoYuNa/026.png b/src/resources/image/MaoYuNa/026.png new file mode 100644 index 0000000..8407f1c Binary files /dev/null and b/src/resources/image/MaoYuNa/026.png differ diff --git a/src/resources/image/MaoYuNa/027.png b/src/resources/image/MaoYuNa/027.png new file mode 100644 index 0000000..02cc14c Binary files /dev/null and b/src/resources/image/MaoYuNa/027.png differ diff --git a/src/resources/image/MaoYuNa/028.png b/src/resources/image/MaoYuNa/028.png new file mode 100644 index 0000000..f98d5fd Binary files /dev/null and b/src/resources/image/MaoYuNa/028.png differ diff --git a/src/resources/image/MaoYuNa/029.png b/src/resources/image/MaoYuNa/029.png new file mode 100644 index 0000000..7988d54 Binary files /dev/null and b/src/resources/image/MaoYuNa/029.png differ diff --git a/src/resources/image/MaoYuNa/030.png b/src/resources/image/MaoYuNa/030.png new file mode 100644 index 0000000..ba09c13 Binary files /dev/null and b/src/resources/image/MaoYuNa/030.png differ diff --git a/src/resources/image/codeforces/cfContestQR.png b/src/resources/image/codeforces/cfContestQR.png new file mode 100644 index 0000000..67b387e Binary files /dev/null and b/src/resources/image/codeforces/cfContestQR.png differ diff --git a/src/resources/image/github_repo/SanYeCao-Nonebot.png b/src/resources/image/github_repo/SanYeCao-Nonebot.png new file mode 100644 index 0000000..daec067 Binary files /dev/null and b/src/resources/image/github_repo/SanYeCao-Nonebot.png differ diff --git a/src/resources/image/github_repo/SanYeCao-Nonebot2.jpg b/src/resources/image/github_repo/SanYeCao-Nonebot2.jpg new file mode 100644 index 0000000..652de2a Binary files /dev/null and b/src/resources/image/github_repo/SanYeCao-Nonebot2.jpg differ diff --git a/src/resources/image/github_repo/SanYeCao-Nonebot3.png b/src/resources/image/github_repo/SanYeCao-Nonebot3.png new file mode 100644 index 0000000..6075ecd Binary files /dev/null and b/src/resources/image/github_repo/SanYeCao-Nonebot3.png differ diff --git a/src/resources/image/good_bad_news/bad_news.png b/src/resources/image/good_bad_news/bad_news.png new file mode 100644 index 0000000..e2b441c Binary files /dev/null and b/src/resources/image/good_bad_news/bad_news.png differ diff --git a/src/resources/image/good_bad_news/good_news.png b/src/resources/image/good_bad_news/good_news.png new file mode 100644 index 0000000..c2e214a Binary files /dev/null and b/src/resources/image/good_bad_news/good_news.png differ diff --git a/src/resources/image/rua/1.png b/src/resources/image/rua/1.png new file mode 100644 index 0000000..11e468c Binary files /dev/null and b/src/resources/image/rua/1.png differ diff --git a/src/resources/image/rua/10.png b/src/resources/image/rua/10.png new file mode 100644 index 0000000..63f7c7b Binary files /dev/null and b/src/resources/image/rua/10.png differ diff --git a/src/resources/image/rua/2.png b/src/resources/image/rua/2.png new file mode 100644 index 0000000..11e468c Binary files /dev/null and b/src/resources/image/rua/2.png differ diff --git a/src/resources/image/rua/3.png b/src/resources/image/rua/3.png new file mode 100644 index 0000000..204c879 Binary files /dev/null and b/src/resources/image/rua/3.png differ diff --git a/src/resources/image/rua/4.png b/src/resources/image/rua/4.png new file mode 100644 index 0000000..204c879 Binary files /dev/null and b/src/resources/image/rua/4.png differ diff --git a/src/resources/image/rua/5.png b/src/resources/image/rua/5.png new file mode 100644 index 0000000..4ccfddd Binary files /dev/null and b/src/resources/image/rua/5.png differ diff --git a/src/resources/image/rua/6.png b/src/resources/image/rua/6.png new file mode 100644 index 0000000..4ccfddd Binary files /dev/null and b/src/resources/image/rua/6.png differ diff --git a/src/resources/image/rua/7.png b/src/resources/image/rua/7.png new file mode 100644 index 0000000..f20902f Binary files /dev/null and b/src/resources/image/rua/7.png differ diff --git a/src/resources/image/rua/8.png b/src/resources/image/rua/8.png new file mode 100644 index 0000000..f20902f Binary files /dev/null and b/src/resources/image/rua/8.png differ diff --git a/src/resources/image/rua/9.png b/src/resources/image/rua/9.png new file mode 100644 index 0000000..63f7c7b Binary files /dev/null and b/src/resources/image/rua/9.png differ diff --git a/src/resources/image/tarot/TarotImages/Ace of Coins.jpg b/src/resources/image/tarot/TarotImages/Ace of Coins.jpg new file mode 100644 index 0000000..120619e Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Ace of Coins.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Ace of Cups.jpg b/src/resources/image/tarot/TarotImages/Ace of Cups.jpg new file mode 100644 index 0000000..ee53381 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Ace of Cups.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Ace of Swords.jpg b/src/resources/image/tarot/TarotImages/Ace of Swords.jpg new file mode 100644 index 0000000..239aafa Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Ace of Swords.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Ace of Wands.jpg b/src/resources/image/tarot/TarotImages/Ace of Wands.jpg new file mode 100644 index 0000000..f34b8a6 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Ace of Wands.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Death.jpg b/src/resources/image/tarot/TarotImages/Death.jpg new file mode 100644 index 0000000..cd8f86d Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Death.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Five of Cups.png b/src/resources/image/tarot/TarotImages/Five of Cups.png new file mode 100644 index 0000000..9e74a9e Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Five of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/Five of Wands.png b/src/resources/image/tarot/TarotImages/Five of Wands.png new file mode 100644 index 0000000..86c95d7 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Five of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Four of Swords.png b/src/resources/image/tarot/TarotImages/Four of Swords.png new file mode 100644 index 0000000..d9ae4b6 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Four of Swords.png differ diff --git a/src/resources/image/tarot/TarotImages/Judgement.jpg b/src/resources/image/tarot/TarotImages/Judgement.jpg new file mode 100644 index 0000000..c7c113a Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Judgement.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Justice.jpg b/src/resources/image/tarot/TarotImages/Justice.jpg new file mode 100644 index 0000000..ce37881 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Justice.jpg differ diff --git a/src/resources/image/tarot/TarotImages/King of Cups.png b/src/resources/image/tarot/TarotImages/King of Cups.png new file mode 100644 index 0000000..bbd7cc5 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/King of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/King of Pentacles.png b/src/resources/image/tarot/TarotImages/King of Pentacles.png new file mode 100644 index 0000000..4dfb348 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/King of Pentacles.png differ diff --git a/src/resources/image/tarot/TarotImages/King of Swords.png b/src/resources/image/tarot/TarotImages/King of Swords.png new file mode 100644 index 0000000..6fb03f1 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/King of Swords.png differ diff --git a/src/resources/image/tarot/TarotImages/King of Wands.png b/src/resources/image/tarot/TarotImages/King of Wands.png new file mode 100644 index 0000000..88ea9b6 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/King of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Knight of Cups.png b/src/resources/image/tarot/TarotImages/Knight of Cups.png new file mode 100644 index 0000000..7c4bd9e Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Knight of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/Knight of Pentacles.png b/src/resources/image/tarot/TarotImages/Knight of Pentacles.png new file mode 100644 index 0000000..cd32989 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Knight of Pentacles.png differ diff --git a/src/resources/image/tarot/TarotImages/Knight of Swords.png b/src/resources/image/tarot/TarotImages/Knight of Swords.png new file mode 100644 index 0000000..6092010 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Knight of Swords.png differ diff --git a/src/resources/image/tarot/TarotImages/Knight of Wands.png b/src/resources/image/tarot/TarotImages/Knight of Wands.png new file mode 100644 index 0000000..9b8ed16 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Knight of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Nine of Cups.png b/src/resources/image/tarot/TarotImages/Nine of Cups.png new file mode 100644 index 0000000..d90babd Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Nine of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/Page of Cups.png b/src/resources/image/tarot/TarotImages/Page of Cups.png new file mode 100644 index 0000000..136d933 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Page of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/Page of Pentacles.png b/src/resources/image/tarot/TarotImages/Page of Pentacles.png new file mode 100644 index 0000000..f976bab Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Page of Pentacles.png differ diff --git a/src/resources/image/tarot/TarotImages/Page of Swords.png b/src/resources/image/tarot/TarotImages/Page of Swords.png new file mode 100644 index 0000000..1e4ff9c Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Page of Swords.png differ diff --git a/src/resources/image/tarot/TarotImages/Page of Wands.png b/src/resources/image/tarot/TarotImages/Page of Wands.png new file mode 100644 index 0000000..c7c5b4f Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Page of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Queen of Cups.png b/src/resources/image/tarot/TarotImages/Queen of Cups.png new file mode 100644 index 0000000..37a1804 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Queen of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/Queen of Pentacles.png b/src/resources/image/tarot/TarotImages/Queen of Pentacles.png new file mode 100644 index 0000000..09aa653 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Queen of Pentacles.png differ diff --git a/src/resources/image/tarot/TarotImages/Queen of Swords.png b/src/resources/image/tarot/TarotImages/Queen of Swords.png new file mode 100644 index 0000000..9f7bb98 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Queen of Swords.png differ diff --git a/src/resources/image/tarot/TarotImages/Queen of Wands.png b/src/resources/image/tarot/TarotImages/Queen of Wands.png new file mode 100644 index 0000000..568bfd5 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Queen of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Six of Wands.png b/src/resources/image/tarot/TarotImages/Six of Wands.png new file mode 100644 index 0000000..9d7aee5 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Six of Wands.png differ diff --git a/src/resources/image/tarot/TarotImages/Strength.jpg b/src/resources/image/tarot/TarotImages/Strength.jpg new file mode 100644 index 0000000..fd66b54 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Strength.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Temperance.jpg b/src/resources/image/tarot/TarotImages/Temperance.jpg new file mode 100644 index 0000000..b79b2c3 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Temperance.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Ten of Cups.png b/src/resources/image/tarot/TarotImages/Ten of Cups.png new file mode 100644 index 0000000..80b57cc Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Ten of Cups.png differ diff --git a/src/resources/image/tarot/TarotImages/The Chariot.jpg b/src/resources/image/tarot/TarotImages/The Chariot.jpg new file mode 100644 index 0000000..f7bd93e Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Chariot.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Devil.jpg b/src/resources/image/tarot/TarotImages/The Devil.jpg new file mode 100644 index 0000000..3cf10f9 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Devil.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Emperor.jpg b/src/resources/image/tarot/TarotImages/The Emperor.jpg new file mode 100644 index 0000000..36034c4 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Emperor.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Empress.jpg b/src/resources/image/tarot/TarotImages/The Empress.jpg new file mode 100644 index 0000000..68927c9 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Empress.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Fool.jpg b/src/resources/image/tarot/TarotImages/The Fool.jpg new file mode 100644 index 0000000..2df2dfa Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Fool.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Hanged Man.jpg b/src/resources/image/tarot/TarotImages/The Hanged Man.jpg new file mode 100644 index 0000000..e05a5b6 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Hanged Man.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Hermit.jpg b/src/resources/image/tarot/TarotImages/The Hermit.jpg new file mode 100644 index 0000000..e3d2193 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Hermit.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Hierophant.jpg b/src/resources/image/tarot/TarotImages/The Hierophant.jpg new file mode 100644 index 0000000..1535d4b Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Hierophant.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The High Priestess.jpg b/src/resources/image/tarot/TarotImages/The High Priestess.jpg new file mode 100644 index 0000000..28f2923 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The High Priestess.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Lovers.jpg b/src/resources/image/tarot/TarotImages/The Lovers.jpg new file mode 100644 index 0000000..e001919 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Lovers.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Magician.jpg b/src/resources/image/tarot/TarotImages/The Magician.jpg new file mode 100644 index 0000000..dfea4a0 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Magician.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Moon.jpg b/src/resources/image/tarot/TarotImages/The Moon.jpg new file mode 100644 index 0000000..cfeeacf Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Moon.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Star.jpg b/src/resources/image/tarot/TarotImages/The Star.jpg new file mode 100644 index 0000000..82bae77 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Star.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Sun.jpg b/src/resources/image/tarot/TarotImages/The Sun.jpg new file mode 100644 index 0000000..169111b Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Sun.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Tower.jpg b/src/resources/image/tarot/TarotImages/The Tower.jpg new file mode 100644 index 0000000..9aca92b Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Tower.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The Wheel of Fortune.jpg b/src/resources/image/tarot/TarotImages/The Wheel of Fortune.jpg new file mode 100644 index 0000000..b9fed19 Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The Wheel of Fortune.jpg differ diff --git a/src/resources/image/tarot/TarotImages/The World.jpg b/src/resources/image/tarot/TarotImages/The World.jpg new file mode 100644 index 0000000..b6994ec Binary files /dev/null and b/src/resources/image/tarot/TarotImages/The World.jpg differ diff --git a/src/resources/image/tarot/TarotImages/Three of Swords.png b/src/resources/image/tarot/TarotImages/Three of Swords.png new file mode 100644 index 0000000..da19c7d Binary files /dev/null and b/src/resources/image/tarot/TarotImages/Three of Swords.png differ diff --git a/src/resources/image/tarot/sideTarotImages/Temperance.jpg b/src/resources/image/tarot/sideTarotImages/Temperance.jpg new file mode 100644 index 0000000..b95ce39 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/Temperance.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Chariot.jpg b/src/resources/image/tarot/sideTarotImages/The Chariot.jpg new file mode 100644 index 0000000..259e057 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Chariot.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Devil.jpg b/src/resources/image/tarot/sideTarotImages/The Devil.jpg new file mode 100644 index 0000000..bafb1b0 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Devil.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Emperor.jpg b/src/resources/image/tarot/sideTarotImages/The Emperor.jpg new file mode 100644 index 0000000..d8444de Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Emperor.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Fool.jpg b/src/resources/image/tarot/sideTarotImages/The Fool.jpg new file mode 100644 index 0000000..7dd2615 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Fool.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Lovers.jpg b/src/resources/image/tarot/sideTarotImages/The Lovers.jpg new file mode 100644 index 0000000..6c6eee4 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Lovers.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Magician.jpg b/src/resources/image/tarot/sideTarotImages/The Magician.jpg new file mode 100644 index 0000000..5b6a901 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Magician.jpg differ diff --git a/src/resources/image/tarot/sideTarotImages/The Sun.jpg b/src/resources/image/tarot/sideTarotImages/The Sun.jpg new file mode 100644 index 0000000..601e469 Binary files /dev/null and b/src/resources/image/tarot/sideTarotImages/The Sun.jpg differ diff --git a/src/resources/image/who_say/luxun.jpg b/src/resources/image/who_say/luxun.jpg new file mode 100644 index 0000000..8b10eaf Binary files /dev/null and b/src/resources/image/who_say/luxun.jpg differ diff --git a/src/resources/log/log b/src/resources/log/log new file mode 100644 index 0000000..e69de29 diff --git a/src/resources/temp/temp b/src/resources/temp/temp new file mode 100644 index 0000000..e69de29