jiajia


Namejiajia JSON
Version 1.1.0 PyPI version JSON
download
home_pagehttps://github.com/xiatian/jiajia
Summary轻量级RSA-AES混合加密框架
upload_time2025-08-01 06:19:07
maintainerNone
docs_urlNone
author夏云龙
requires_python>=3.8
licenseMIT
keywords encryption cryptography rsa aes hmac security hybrid
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # JiaJia - RSA-AES 混合加密框架

一个轻量级的加密解密框架,提供RSA非对称加密、AES对称加密、HMAC签名验证等功能。可以直接在其他项目中import使用。

## 功能特性

- 🔐 **RSA非对称加密**: 支持2048位和4096位密钥
- 🔑 **AES对称加密**: 支持GCM和CBC模式
- ✍️ **HMAC签名验证**: 确保数据完整性和真实性
- 🗂️ **会话管理**: 支持会话创建、存储和失效
- ⚡ **异步支持**: 全异步API设计
- 🛡️ **安全配置**: 灵活的安全参数配置
- 📦 **便捷函数**: 提供简单易用的便捷函数
- 🔄 **缓存支持**: 支持内存和Redis缓存后端

## 安装

```bash
pip install jiajia
```

## 快速开始

### 基本使用

```python
import asyncio
from jiajia import key_exchange, encrypt_data, decrypt_data, set_config, SecurityConfig

async def main():
    # 1. 设置配置
    config = SecurityConfig(
        rsa_key_size=2048,
        aes_mode="GCM",
        session_expire_time=3600
    )
    set_config(config)
    
    # 2. 密钥交换(建立安全会话)
    exchange_result = await key_exchange("client_app", "1.0.0")
    session_id = exchange_result["session_id"]
    
    # 3. 加密数据
    sensitive_data = {"user_id": "12345", "email": "user@example.com"}
    encrypt_result = await encrypt_data(sensitive_data, session_id)
    
    # 4. 解密数据
    decrypt_payload = encrypt_result.copy()
    decrypt_payload["session_id"] = session_id
    decrypt_result = await decrypt_data(decrypt_payload)
    
    print(f"解密结果: {decrypt_result['data']}")

asyncio.run(main())
```

### 高级使用

```python
import asyncio
from jiajia import EncryptionAPI, SecurityConfig

async def advanced_example():
    # 创建自定义配置
    config = SecurityConfig(
        rsa_key_size=4096,
        aes_mode="GCM",
        session_expire_time=7200,
        max_timestamp_diff=600
    )
    
    # 创建API实例
    api = EncryptionAPI(config)
    
    # 密钥交换
    exchange_result = await api.key_exchange("advanced_client", "2.0.0")
    session_id = exchange_result["session_id"]
    
    # 加密数据
    data = {"message": "Hello, World!", "timestamp": 1234567890}
    encrypt_result = await api.encrypt_data(data, session_id)
    
    # 解密数据
    decrypt_payload = encrypt_result.copy()
    decrypt_payload["session_id"] = session_id
    decrypt_result = await api.decrypt_data(decrypt_payload)
    
    # 健康检查
    health_result = await api.health_check()
    
    # 获取安全配置
    config_result = await api.get_security_config()

asyncio.run(advanced_example())
```

## API 参考

### 核心类

#### `SecurityConfig`

安全配置类,用于设置加密参数。

```python
config = SecurityConfig(
    rsa_key_size=2048,        # RSA密钥大小
    aes_mode="GCM",           # AES模式 (GCM/CBC)
    session_expire_time=3600,  # 会话过期时间(秒)
    max_timestamp_diff=300,    # 时间戳容差(秒)
    cache_backend="memory"     # 缓存后端 (memory/redis)
)
```

#### `EncryptionAPI`

主要的加密API类。

```python
api = EncryptionAPI(config)

# 密钥交换
result = await api.key_exchange(client_id, client_version)

# 加密数据
result = await api.encrypt_data(data, session_id)

# 解密数据
result = await api.decrypt_data(payload)

# 会话管理
result = await api.get_session_info(session_id)
result = await api.invalidate_session(session_id)

# 系统状态
result = await api.health_check()
result = await api.get_security_config()
```

#### `EncryptionCore`

加密核心类,提供底层加密功能。

```python
core = EncryptionCore(config)

# RSA操作
private_key, public_key = core.generate_rsa_keypair()
encrypted = core.rsa_encrypt(public_key, data)
decrypted = core.rsa_decrypt(private_key, encrypted)

# AES操作
aes_key = core.generate_aes_key()
iv, ciphertext, tag = core.aes_encrypt(aes_key, data)
decrypted = core.aes_decrypt(aes_key, iv, ciphertext, tag)

# HMAC操作
hmac_key = core.generate_hmac_key()
signature = core.hmac_sign(hmac_key, data)
is_valid = core.hmac_verify(hmac_key, data, signature)
```

#### `SessionManager`

会话管理类,处理会话的创建、存储和验证。

```python
session_manager = SessionManager(config)

# 会话操作
session_info = await session_manager.create_session(client_id, version)
await session_manager.store_keys(session_id, private_key, hmac_key)
await session_manager.store_aes_key(session_id, aes_key)
session_info = await session_manager.get_session_info(session_id)
await session_manager.invalidate_session(session_id)
is_valid = await session_manager.is_session_valid(session_id)
```

### 便捷函数

框架提供了便捷函数,简化常见操作:

```python
from jiajia import (
    key_exchange,
    encrypt_data,
    decrypt_data,
    get_session_info,
    invalidate_session,
    health_check,
    set_config,
    get_api
)

# 设置全局配置
set_config(config)

# 获取全局API实例
api = get_api()

# 使用便捷函数
result = await key_exchange("client", "1.0.0")
result = await encrypt_data(data, session_id)
result = await decrypt_data(payload)
result = await get_session_info(session_id)
result = await invalidate_session(session_id)
result = await health_check()
```

## 配置选项

### 环境变量

可以通过环境变量配置框架:

```bash
export RSA_KEY_SIZE=4096
export AES_MODE=GCM
export SESSION_EXPIRE_TIME=7200
export MAX_TIMESTAMP_DIFF=600
export CACHE_BACKEND=memory
export LOG_LEVEL=INFO
export ENABLE_LOGGING=true
```

### 配置参数

| 参数 | 默认值 | 说明 |
|------|--------|------|
| `rsa_key_size` | 2048 | RSA密钥大小(位) |
| `aes_mode` | "GCM" | AES加密模式 |
| `aes_key_size` | 32 | AES密钥大小(字节) |
| `session_expire_time` | 3600 | 会话过期时间(秒) |
| `max_timestamp_diff` | 300 | 时间戳容差(秒) |
| `cache_backend` | "memory" | 缓存后端类型 |
| `redis_url` | None | Redis连接URL |
| `log_level` | "INFO" | 日志级别 |
| `enable_logging` | True | 是否启用日志 |

## 安全特性

- **混合加密**: 结合RSA和AES的优势
- **HMAC签名**: 确保数据完整性和真实性
- **时间戳验证**: 防止重放攻击
- **会话管理**: 安全的会话生命周期管理
- **密钥轮换**: 支持动态密钥生成和存储

## 性能特性

- **异步设计**: 全异步API,支持高并发
- **缓存支持**: 内存和Redis缓存后端
- **批量操作**: 支持批量数据处理
- **轻量级**: 最小化依赖,快速启动

## 错误处理

框架提供了完善的错误处理机制:

```python
try:
    result = await encrypt_data(data, session_id)
    if result["success"]:
        # 处理成功结果
        pass
    else:
        # 处理错误
        print(f"错误: {result['error']}")
except Exception as e:
    # 处理异常
    print(f"异常: {e}")
```

## 测试

运行测试确保功能正常:

```bash
python -c "
import asyncio
from jiajia import key_exchange, encrypt_data, decrypt_data, SecurityConfig, set_config

async def test():
    config = SecurityConfig()
    set_config(config)
    
    # 测试基本功能
    exchange = await key_exchange('test', '1.0.0')
    session_id = exchange['session_id']
    
    data = {'test': 'data'}
    encrypted = await encrypt_data(data, session_id)
    
    payload = encrypted.copy()
    payload['session_id'] = session_id
    decrypted = await decrypt_data(payload)
    
    print('测试通过!' if decrypted['data'] == data else '测试失败!')

asyncio.run(test())
"
```

## 许可证

MIT License

## 作者

夏云龙

## 版本

1.1.0

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/xiatian/jiajia",
    "name": "jiajia",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "\u590f\u4e91\u9f99 <1900098962@qq.com>",
    "keywords": "encryption, cryptography, rsa, aes, hmac, security, hybrid",
    "author": "\u590f\u4e91\u9f99",
    "author_email": "\u590f\u4e91\u9f99 <1900098962@qq.com>",
    "download_url": "https://files.pythonhosted.org/packages/ac/a4/732594620ec5274c8144b6b18257914639e3e8b94912e948deb3eb13f6b5/jiajia-1.1.0.tar.gz",
    "platform": null,
    "description": "# JiaJia - RSA-AES \u6df7\u5408\u52a0\u5bc6\u6846\u67b6\n\n\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684\u52a0\u5bc6\u89e3\u5bc6\u6846\u67b6\uff0c\u63d0\u4f9bRSA\u975e\u5bf9\u79f0\u52a0\u5bc6\u3001AES\u5bf9\u79f0\u52a0\u5bc6\u3001HMAC\u7b7e\u540d\u9a8c\u8bc1\u7b49\u529f\u80fd\u3002\u53ef\u4ee5\u76f4\u63a5\u5728\u5176\u4ed6\u9879\u76ee\u4e2dimport\u4f7f\u7528\u3002\n\n## \u529f\u80fd\u7279\u6027\n\n- \ud83d\udd10 **RSA\u975e\u5bf9\u79f0\u52a0\u5bc6**: \u652f\u63012048\u4f4d\u548c4096\u4f4d\u5bc6\u94a5\n- \ud83d\udd11 **AES\u5bf9\u79f0\u52a0\u5bc6**: \u652f\u6301GCM\u548cCBC\u6a21\u5f0f\n- \u270d\ufe0f **HMAC\u7b7e\u540d\u9a8c\u8bc1**: \u786e\u4fdd\u6570\u636e\u5b8c\u6574\u6027\u548c\u771f\u5b9e\u6027\n- \ud83d\uddc2\ufe0f **\u4f1a\u8bdd\u7ba1\u7406**: \u652f\u6301\u4f1a\u8bdd\u521b\u5efa\u3001\u5b58\u50a8\u548c\u5931\u6548\n- \u26a1 **\u5f02\u6b65\u652f\u6301**: \u5168\u5f02\u6b65API\u8bbe\u8ba1\n- \ud83d\udee1\ufe0f **\u5b89\u5168\u914d\u7f6e**: \u7075\u6d3b\u7684\u5b89\u5168\u53c2\u6570\u914d\u7f6e\n- \ud83d\udce6 **\u4fbf\u6377\u51fd\u6570**: \u63d0\u4f9b\u7b80\u5355\u6613\u7528\u7684\u4fbf\u6377\u51fd\u6570\n- \ud83d\udd04 **\u7f13\u5b58\u652f\u6301**: \u652f\u6301\u5185\u5b58\u548cRedis\u7f13\u5b58\u540e\u7aef\n\n## \u5b89\u88c5\n\n```bash\npip install jiajia\n```\n\n## \u5feb\u901f\u5f00\u59cb\n\n### \u57fa\u672c\u4f7f\u7528\n\n```python\nimport asyncio\nfrom jiajia import key_exchange, encrypt_data, decrypt_data, set_config, SecurityConfig\n\nasync def main():\n    # 1. \u8bbe\u7f6e\u914d\u7f6e\n    config = SecurityConfig(\n        rsa_key_size=2048,\n        aes_mode=\"GCM\",\n        session_expire_time=3600\n    )\n    set_config(config)\n    \n    # 2. \u5bc6\u94a5\u4ea4\u6362\uff08\u5efa\u7acb\u5b89\u5168\u4f1a\u8bdd\uff09\n    exchange_result = await key_exchange(\"client_app\", \"1.0.0\")\n    session_id = exchange_result[\"session_id\"]\n    \n    # 3. \u52a0\u5bc6\u6570\u636e\n    sensitive_data = {\"user_id\": \"12345\", \"email\": \"user@example.com\"}\n    encrypt_result = await encrypt_data(sensitive_data, session_id)\n    \n    # 4. \u89e3\u5bc6\u6570\u636e\n    decrypt_payload = encrypt_result.copy()\n    decrypt_payload[\"session_id\"] = session_id\n    decrypt_result = await decrypt_data(decrypt_payload)\n    \n    print(f\"\u89e3\u5bc6\u7ed3\u679c: {decrypt_result['data']}\")\n\nasyncio.run(main())\n```\n\n### \u9ad8\u7ea7\u4f7f\u7528\n\n```python\nimport asyncio\nfrom jiajia import EncryptionAPI, SecurityConfig\n\nasync def advanced_example():\n    # \u521b\u5efa\u81ea\u5b9a\u4e49\u914d\u7f6e\n    config = SecurityConfig(\n        rsa_key_size=4096,\n        aes_mode=\"GCM\",\n        session_expire_time=7200,\n        max_timestamp_diff=600\n    )\n    \n    # \u521b\u5efaAPI\u5b9e\u4f8b\n    api = EncryptionAPI(config)\n    \n    # \u5bc6\u94a5\u4ea4\u6362\n    exchange_result = await api.key_exchange(\"advanced_client\", \"2.0.0\")\n    session_id = exchange_result[\"session_id\"]\n    \n    # \u52a0\u5bc6\u6570\u636e\n    data = {\"message\": \"Hello, World!\", \"timestamp\": 1234567890}\n    encrypt_result = await api.encrypt_data(data, session_id)\n    \n    # \u89e3\u5bc6\u6570\u636e\n    decrypt_payload = encrypt_result.copy()\n    decrypt_payload[\"session_id\"] = session_id\n    decrypt_result = await api.decrypt_data(decrypt_payload)\n    \n    # \u5065\u5eb7\u68c0\u67e5\n    health_result = await api.health_check()\n    \n    # \u83b7\u53d6\u5b89\u5168\u914d\u7f6e\n    config_result = await api.get_security_config()\n\nasyncio.run(advanced_example())\n```\n\n## API \u53c2\u8003\n\n### \u6838\u5fc3\u7c7b\n\n#### `SecurityConfig`\n\n\u5b89\u5168\u914d\u7f6e\u7c7b\uff0c\u7528\u4e8e\u8bbe\u7f6e\u52a0\u5bc6\u53c2\u6570\u3002\n\n```python\nconfig = SecurityConfig(\n    rsa_key_size=2048,        # RSA\u5bc6\u94a5\u5927\u5c0f\n    aes_mode=\"GCM\",           # AES\u6a21\u5f0f (GCM/CBC)\n    session_expire_time=3600,  # \u4f1a\u8bdd\u8fc7\u671f\u65f6\u95f4\uff08\u79d2\uff09\n    max_timestamp_diff=300,    # \u65f6\u95f4\u6233\u5bb9\u5dee\uff08\u79d2\uff09\n    cache_backend=\"memory\"     # \u7f13\u5b58\u540e\u7aef (memory/redis)\n)\n```\n\n#### `EncryptionAPI`\n\n\u4e3b\u8981\u7684\u52a0\u5bc6API\u7c7b\u3002\n\n```python\napi = EncryptionAPI(config)\n\n# \u5bc6\u94a5\u4ea4\u6362\nresult = await api.key_exchange(client_id, client_version)\n\n# \u52a0\u5bc6\u6570\u636e\nresult = await api.encrypt_data(data, session_id)\n\n# \u89e3\u5bc6\u6570\u636e\nresult = await api.decrypt_data(payload)\n\n# \u4f1a\u8bdd\u7ba1\u7406\nresult = await api.get_session_info(session_id)\nresult = await api.invalidate_session(session_id)\n\n# \u7cfb\u7edf\u72b6\u6001\nresult = await api.health_check()\nresult = await api.get_security_config()\n```\n\n#### `EncryptionCore`\n\n\u52a0\u5bc6\u6838\u5fc3\u7c7b\uff0c\u63d0\u4f9b\u5e95\u5c42\u52a0\u5bc6\u529f\u80fd\u3002\n\n```python\ncore = EncryptionCore(config)\n\n# RSA\u64cd\u4f5c\nprivate_key, public_key = core.generate_rsa_keypair()\nencrypted = core.rsa_encrypt(public_key, data)\ndecrypted = core.rsa_decrypt(private_key, encrypted)\n\n# AES\u64cd\u4f5c\naes_key = core.generate_aes_key()\niv, ciphertext, tag = core.aes_encrypt(aes_key, data)\ndecrypted = core.aes_decrypt(aes_key, iv, ciphertext, tag)\n\n# HMAC\u64cd\u4f5c\nhmac_key = core.generate_hmac_key()\nsignature = core.hmac_sign(hmac_key, data)\nis_valid = core.hmac_verify(hmac_key, data, signature)\n```\n\n#### `SessionManager`\n\n\u4f1a\u8bdd\u7ba1\u7406\u7c7b\uff0c\u5904\u7406\u4f1a\u8bdd\u7684\u521b\u5efa\u3001\u5b58\u50a8\u548c\u9a8c\u8bc1\u3002\n\n```python\nsession_manager = SessionManager(config)\n\n# \u4f1a\u8bdd\u64cd\u4f5c\nsession_info = await session_manager.create_session(client_id, version)\nawait session_manager.store_keys(session_id, private_key, hmac_key)\nawait session_manager.store_aes_key(session_id, aes_key)\nsession_info = await session_manager.get_session_info(session_id)\nawait session_manager.invalidate_session(session_id)\nis_valid = await session_manager.is_session_valid(session_id)\n```\n\n### \u4fbf\u6377\u51fd\u6570\n\n\u6846\u67b6\u63d0\u4f9b\u4e86\u4fbf\u6377\u51fd\u6570\uff0c\u7b80\u5316\u5e38\u89c1\u64cd\u4f5c\uff1a\n\n```python\nfrom jiajia import (\n    key_exchange,\n    encrypt_data,\n    decrypt_data,\n    get_session_info,\n    invalidate_session,\n    health_check,\n    set_config,\n    get_api\n)\n\n# \u8bbe\u7f6e\u5168\u5c40\u914d\u7f6e\nset_config(config)\n\n# \u83b7\u53d6\u5168\u5c40API\u5b9e\u4f8b\napi = get_api()\n\n# \u4f7f\u7528\u4fbf\u6377\u51fd\u6570\nresult = await key_exchange(\"client\", \"1.0.0\")\nresult = await encrypt_data(data, session_id)\nresult = await decrypt_data(payload)\nresult = await get_session_info(session_id)\nresult = await invalidate_session(session_id)\nresult = await health_check()\n```\n\n## \u914d\u7f6e\u9009\u9879\n\n### \u73af\u5883\u53d8\u91cf\n\n\u53ef\u4ee5\u901a\u8fc7\u73af\u5883\u53d8\u91cf\u914d\u7f6e\u6846\u67b6\uff1a\n\n```bash\nexport RSA_KEY_SIZE=4096\nexport AES_MODE=GCM\nexport SESSION_EXPIRE_TIME=7200\nexport MAX_TIMESTAMP_DIFF=600\nexport CACHE_BACKEND=memory\nexport LOG_LEVEL=INFO\nexport ENABLE_LOGGING=true\n```\n\n### \u914d\u7f6e\u53c2\u6570\n\n| \u53c2\u6570 | \u9ed8\u8ba4\u503c | \u8bf4\u660e |\n|------|--------|------|\n| `rsa_key_size` | 2048 | RSA\u5bc6\u94a5\u5927\u5c0f\uff08\u4f4d\uff09 |\n| `aes_mode` | \"GCM\" | AES\u52a0\u5bc6\u6a21\u5f0f |\n| `aes_key_size` | 32 | AES\u5bc6\u94a5\u5927\u5c0f\uff08\u5b57\u8282\uff09 |\n| `session_expire_time` | 3600 | \u4f1a\u8bdd\u8fc7\u671f\u65f6\u95f4\uff08\u79d2\uff09 |\n| `max_timestamp_diff` | 300 | \u65f6\u95f4\u6233\u5bb9\u5dee\uff08\u79d2\uff09 |\n| `cache_backend` | \"memory\" | \u7f13\u5b58\u540e\u7aef\u7c7b\u578b |\n| `redis_url` | None | Redis\u8fde\u63a5URL |\n| `log_level` | \"INFO\" | \u65e5\u5fd7\u7ea7\u522b |\n| `enable_logging` | True | \u662f\u5426\u542f\u7528\u65e5\u5fd7 |\n\n## \u5b89\u5168\u7279\u6027\n\n- **\u6df7\u5408\u52a0\u5bc6**: \u7ed3\u5408RSA\u548cAES\u7684\u4f18\u52bf\n- **HMAC\u7b7e\u540d**: \u786e\u4fdd\u6570\u636e\u5b8c\u6574\u6027\u548c\u771f\u5b9e\u6027\n- **\u65f6\u95f4\u6233\u9a8c\u8bc1**: \u9632\u6b62\u91cd\u653e\u653b\u51fb\n- **\u4f1a\u8bdd\u7ba1\u7406**: \u5b89\u5168\u7684\u4f1a\u8bdd\u751f\u547d\u5468\u671f\u7ba1\u7406\n- **\u5bc6\u94a5\u8f6e\u6362**: \u652f\u6301\u52a8\u6001\u5bc6\u94a5\u751f\u6210\u548c\u5b58\u50a8\n\n## \u6027\u80fd\u7279\u6027\n\n- **\u5f02\u6b65\u8bbe\u8ba1**: \u5168\u5f02\u6b65API\uff0c\u652f\u6301\u9ad8\u5e76\u53d1\n- **\u7f13\u5b58\u652f\u6301**: \u5185\u5b58\u548cRedis\u7f13\u5b58\u540e\u7aef\n- **\u6279\u91cf\u64cd\u4f5c**: \u652f\u6301\u6279\u91cf\u6570\u636e\u5904\u7406\n- **\u8f7b\u91cf\u7ea7**: \u6700\u5c0f\u5316\u4f9d\u8d56\uff0c\u5feb\u901f\u542f\u52a8\n\n## \u9519\u8bef\u5904\u7406\n\n\u6846\u67b6\u63d0\u4f9b\u4e86\u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\u673a\u5236\uff1a\n\n```python\ntry:\n    result = await encrypt_data(data, session_id)\n    if result[\"success\"]:\n        # \u5904\u7406\u6210\u529f\u7ed3\u679c\n        pass\n    else:\n        # \u5904\u7406\u9519\u8bef\n        print(f\"\u9519\u8bef: {result['error']}\")\nexcept Exception as e:\n    # \u5904\u7406\u5f02\u5e38\n    print(f\"\u5f02\u5e38: {e}\")\n```\n\n## \u6d4b\u8bd5\n\n\u8fd0\u884c\u6d4b\u8bd5\u786e\u4fdd\u529f\u80fd\u6b63\u5e38\uff1a\n\n```bash\npython -c \"\nimport asyncio\nfrom jiajia import key_exchange, encrypt_data, decrypt_data, SecurityConfig, set_config\n\nasync def test():\n    config = SecurityConfig()\n    set_config(config)\n    \n    # \u6d4b\u8bd5\u57fa\u672c\u529f\u80fd\n    exchange = await key_exchange('test', '1.0.0')\n    session_id = exchange['session_id']\n    \n    data = {'test': 'data'}\n    encrypted = await encrypt_data(data, session_id)\n    \n    payload = encrypted.copy()\n    payload['session_id'] = session_id\n    decrypted = await decrypt_data(payload)\n    \n    print('\u6d4b\u8bd5\u901a\u8fc7!' if decrypted['data'] == data else '\u6d4b\u8bd5\u5931\u8d25!')\n\nasyncio.run(test())\n\"\n```\n\n## \u8bb8\u53ef\u8bc1\n\nMIT License\n\n## \u4f5c\u8005\n\n\u590f\u4e91\u9f99\n\n## \u7248\u672c\n\n1.1.0\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u8f7b\u91cf\u7ea7RSA-AES\u6df7\u5408\u52a0\u5bc6\u6846\u67b6",
    "version": "1.1.0",
    "project_urls": {
        "Documentation": "https://github.com/xiatian/jiajia#readme",
        "Homepage": "https://github.com/xiatian/jiajia",
        "Issues": "https://github.com/xiatian/jiajia/issues",
        "Repository": "https://github.com/xiatian/jiajia"
    },
    "split_keywords": [
        "encryption",
        " cryptography",
        " rsa",
        " aes",
        " hmac",
        " security",
        " hybrid"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ed570b8f90f2f4c29868e9caa20dbc50e5f0790dfaf2510ec2ffc69f2f91f844",
                "md5": "15a2bc3fa5bf2c6cf2fe73bcec846f8c",
                "sha256": "98625965694c92b916294911b27f2b4fc79664b3a85fb6337617a4e12830ca3e"
            },
            "downloads": -1,
            "filename": "jiajia-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "15a2bc3fa5bf2c6cf2fe73bcec846f8c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 14319,
            "upload_time": "2025-08-01T06:19:06",
            "upload_time_iso_8601": "2025-08-01T06:19:06.131593Z",
            "url": "https://files.pythonhosted.org/packages/ed/57/0b8f90f2f4c29868e9caa20dbc50e5f0790dfaf2510ec2ffc69f2f91f844/jiajia-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "aca4732594620ec5274c8144b6b18257914639e3e8b94912e948deb3eb13f6b5",
                "md5": "1097a0a41cc1c7fc897f6164cc9c9b41",
                "sha256": "5cf700c9ea2f471589968a2be05b8218d47561668ac4c54791f31803132a77d4"
            },
            "downloads": -1,
            "filename": "jiajia-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "1097a0a41cc1c7fc897f6164cc9c9b41",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 15599,
            "upload_time": "2025-08-01T06:19:07",
            "upload_time_iso_8601": "2025-08-01T06:19:07.323252Z",
            "url": "https://files.pythonhosted.org/packages/ac/a4/732594620ec5274c8144b6b18257914639e3e8b94912e948deb3eb13f6b5/jiajia-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-01 06:19:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "xiatian",
    "github_project": "jiajia",
    "github_not_found": true,
    "lcname": "jiajia"
}
        
Elapsed time: 1.26326s