能否使用神经网络模型学习到sha256的规律
·
能否使用神经网络模型学习到sha256的规律
简短回答:不能有效学习到。
详细解释:
SHA-256 是一种加密哈希函数,它的设计目标就是让输出(哈希值)对于输入来说不可预测且无模式可循。具体特点包括:
- 雪崩效应:哪怕输入只改变一位,输出哈希值也会完全不同,且无法通过比较推测出变化模式。
- 抗碰撞性:很难找到两个不同输入拥有相同输出。
- 抗预映像性:给定一个输出,几乎不可能推测出它对应的输入。
- 均匀分布:哈希结果在输出空间中分布得非常均匀,无明显统计规律。
而神经网络(尤其是标准的前馈神经网络或Transformer等)擅长学习有统计规律的数据,比如:
- 图像识别(像素有局部相关性)
- 自然语言处理(单词序列有语法和语义规律)
- 时间序列预测(值随时间有依赖关系)
但是,SHA-256特意破坏了任何可学的统计规律。
哪怕是再深、再大的神经网络,也只能做到跟“瞎猜”差不多的效果,比如输出 256位随机比特流,和真实SHA-256差别很大。
总结:
- 神经网络无法有效学习 SHA-256 的映射规律。
- 训练出来的模型表现不会比随机猜测好。
- 这实际上也是加密学的基本保障之一:让机器和人类都难以逆推出加密过程。
测试代码
- 小批量数据时损失值可以下降,大样本时基本保持不变,准确率为0
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import random
from transformers import BertModel, BertConfig
import hashlib
# ==== 1. 字符表定义 ====
# 输入字符表:数字+大写字母(36个)
input_vocab = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
input_vocab_size = len(input_vocab) + 2 # 加上 [PAD] 和 [UNK]
input_char2id = {c: i + 2 for i, c in enumerate(input_vocab)}
input_char2id['[PAD]'] = 0
input_char2id['[UNK]'] = 1
input_id2char = {i: c for c, i in input_char2id.items()}
# 输出字符表:字母(大小写)、数字、常见特殊字符(你可以按需扩展)
output_vocab = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
output_vocab_size = len(output_vocab)
output_char2id = {c: i for i, c in enumerate(output_vocab)}
output_id2char = {i: c for c, i in output_char2id.items()}
# ==== 2. 工具函数 ====
def encode_input(text):
ids = []
for c in text:
ids.append(input_char2id.get(c, input_char2id['[UNK]']))
return ids
def decode_input(ids):
return ''.join([input_id2char.get(i, '[UNK]') for i in ids])
def encode_output(text):
return [output_char2id[c] for c in text]
def decode_output(ids):
return ''.join([output_id2char[i] for i in ids])
# ==== 3. 数据集定义 ====
class RandomDataset(Dataset):
def __init__(self, num_samples=10000):
super().__init__()
self.samples = []
for _ in range(num_samples):
output_text = ''.join(random.choices(output_vocab, k=8))
input_text = hashlib.sha256(output_text.encode("utf-8")).hexdigest().upper()
self.samples.append((input_text, output_text))
def __len__(self):
return len(self.samples)
def __getitem__(self, idx):
input_text, output_text = self.samples[idx]
input_ids = encode_input(input_text)
output_ids = encode_output(output_text)
return {
'input_ids': torch.tensor(input_ids, dtype=torch.long),
'output_ids': torch.tensor(output_ids, dtype=torch.long),
}
# ==== 4. 模型定义 ====
class CharBertModel(nn.Module):
def __init__(self, input_vocab_size, output_vocab_size, hidden_size=256):
super(CharBertModel, self).__init__()
config = BertConfig(
vocab_size=input_vocab_size,
hidden_size=hidden_size,
num_hidden_layers=4,
num_attention_heads=4,
intermediate_size=hidden_size * 4,
max_position_embeddings=64,
pad_token_id=0
)
self.bert = BertModel(config)
self.fc = nn.Linear(hidden_size, 8 * output_vocab_size)
self.output_vocab_size = output_vocab_size
def forward(self, input_ids, attention_mask=None):
outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
pooled_output = outputs.pooler_output # (batch_size, hidden_size)
logits = self.fc(pooled_output) # (batch_size, 8 * output_vocab_size)
logits = logits.view(-1, 8, self.output_vocab_size)
return logits
# ==== 5. 小demo训练 ====
def train_demo(batch_size, num_epochs, learning_rate, num_samples, device):
# 数据
dataset = RandomDataset(num_samples=num_samples)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 模型
device = torch.device(device)
model = CharBertModel(input_vocab_size, output_vocab_size)
model.to(device)
# 优化器、损失
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
criterion = nn.CrossEntropyLoss()
for epoch in range(num_epochs):
model.train()
total_loss = 0
for batch in dataloader:
input_ids = batch['input_ids'].to(device)
output_ids = batch['output_ids'].to(device)
attention_mask = (input_ids != 0).long()
logits = model(input_ids, attention_mask)
loss = criterion(logits.view(-1, output_vocab_size), output_ids.view(-1))
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch + 1}/{num_epochs} - Loss: {total_loss / len(dataloader):.4f}")
print("训练完成!🎯")
torch.save(model, "sha256_2_text.pth")
print("保存模型....")
return model
def test(model, test_num, batch_size, device):
print("------------测试模型--------------")
# 测试一组
model.eval()
dataset = RandomDataset(num_samples=test_num)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
count = 0.0
for batch in dataloader:
input_ids = batch['input_ids'].to(device)
output_ids = batch['output_ids'].to(device).tolist()
attention_mask = (input_ids != 0).long()
with torch.no_grad():
output_logits = model(input_ids, attention_mask)
output_pred = output_logits.argmax(dim=-1).squeeze(0)
for i, j in enumerate(output_pred.cpu().tolist(), start=0):
output = decode_output(j)
source_output = decode_output(output_ids[i])
print(output, source_output)
if output == source_output:
count += 1
print(f"命中数量: {count}")
print(f"总数量: {test_num}")
print(f"命中率: {count / test_num}")
# ==== 6. 开始训练 ====
if __name__ == "__main__":
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 超参数
batch_size = 512
num_epochs = 30
learning_rate = 5e-4
num_samples = 50000
model = train_demo(batch_size, num_epochs, learning_rate, num_samples, device)
# 加载保存的模型
# model = torch.load("./sha256_2_text.pth", map_location=torch.device(device), weights_only=False)
test(model, 10000, batch_size, device)
更多推荐
所有评论(0)