能否使用神经网络模型学习到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)
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐