String.sha256_text
2026/4/14大约 4 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — String.sha256_text
String.sha256_text
定义
String.sha256_text 就是把一段文字变成一个更安全的"指纹"——一串固定 64 个字符的十六进制字符串。SHA-256 是比 MD5 更强大的哈希算法,产生的指纹更长、碰撞概率更低(即两个不同的输入产生相同指纹的可能性极小)。
打个比方:如果 MD5 是一个普通的印章,SHA-256 就是一个银行级别的防伪印章——更精密、更难伪造。同样的文件盖出来的印章永远一样,但几乎不可能找到两个不同的文件盖出一样的印章。
在实际游戏开发中,SHA-256 适合用于:密码哈希存储、数据完整性校验、生成安全的唯一标识符等需要更高安全性的场景。
函数签名
C#
// C# 中使用 System.Security.Cryptography
using System.Security.Cryptography;
using System.Text;
public static string Sha256Text(string input)
{
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(hash).ToLower();
}GDScript
func sha256_text() -> String
# 也可以对 PackedByteArray 使用:
# var hash = data.sha256_string()参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| 无 | — | — | 此方法没有参数(作用于字符串自身) |
返回值
String —— 返回 64 个字符的十六进制字符串(小写)。例如 "185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969"。
代码示例
基础用法:计算字符串的 SHA-256 值
C#
using System.Security.Cryptography;
using System.Text;
string input = "Hello World";
string hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(input))).ToLower();
GD.Print(hash);
// 运行结果: "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
string empty = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(""))).ToLower();
GD.Print(empty);
// 运行结果: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"GDScript
var input = "Hello World"
var hash = input.sha256_text()
print(hash)
# 运行结果: "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
var empty = "".sha256_text()
print(empty)
# 运行结果: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"实际场景:带盐值的密码存储
C#
using Godot;
using System.Security.Cryptography;
using System.Text;
public partial class AuthManager : Node
{
public string HashPassword(string password, string salt)
{
string salted = salt + password + salt;
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(salted));
return Convert.ToHexString(hash).ToLower();
// 运行结果: 返回带盐值的 SHA-256 哈希
}
public string GenerateSalt()
{
byte[] randomBytes = new byte[16];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomBytes);
return Convert.ToHexString(randomBytes).ToLower();
// 运行结果: 生成 32 字符的随机盐值
}
public bool VerifyPassword(string password, string salt, string storedHash)
{
string computedHash = HashPassword(password, salt);
bool match = computedHash == storedHash;
GD.Print($"密码验证:{(match ? "正确" : "错误")}");
// 运行结果: 密码正确打印"正确",否则打印"错误"
return match;
}
}GDScript
extends Node
func hash_password(password: String, salt: String) -> String:
var salted = salt + password + salt
return salted.sha256_text()
# 运行结果: 返回带盐值的 SHA-256 哈希
func generate_salt() -> String:
var random_bytes = randi() as int
return str(random_bytes).sha256_text().substr(0, 32)
# 运行结果: 生成 32 字符的随机盐值
func verify_password(password: String, salt: String, stored_hash: String) -> bool:
var computed_hash = hash_password(password, salt)
var match = computed_hash == stored_hash
print("密码验证:%s" % ("正确" if match else "错误"))
# 运行结果: 密码正确打印"正确",否则打印"错误"
return match进阶用法:验证资源文件完整性
C#
using Godot;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
public partial class AssetVerifier : Node
{
private Dictionary<string, string> _assetHashes = new();
public void RegisterAssetHash(string assetPath)
{
var file = FileAccess.Open(assetPath, FileAccess.ModeFlags.Read);
if (file == null) return;
byte[] data = file.GetBuffer((long)file.GetLength());
file.Close();
string hash = Convert.ToHexString(SHA256.HashData(data)).ToLower();
_assetHashes[assetPath] = hash;
GD.Print($"资源注册:{assetPath} -> {hash[..16]}...");
// 运行结果: 打印资源路径和哈希前 16 位
}
public bool VerifyAsset(string assetPath)
{
if (!_assetHashes.ContainsKey(assetPath)) return false;
var file = FileAccess.Open(assetPath, FileAccess.ModeFlags.Read);
if (file == null) return false;
byte[] data = file.GetBuffer((long)file.GetLength());
file.Close();
string currentHash = Convert.ToHexString(SHA256.HashData(data)).ToLower();
bool valid = currentHash == _assetHashes[assetPath];
GD.Print($"资源验证 {assetPath}:{(valid ? "完整" : "已损坏")}");
// 运行结果: 文件完整打印"完整",否则打印"已损坏"
return valid;
}
}GDScript
extends Node
var _asset_hashes: Dictionary = {}
func register_asset_hash(asset_path: String):
var file = FileAccess.open(asset_path, FileAccess.READ)
if file == null:
return
var data = file.get_buffer(file.get_length())
file.close()
var hash = data.sha256_string()
_asset_hashes[asset_path] = hash
print("资源注册:%s -> %s..." % [asset_path, hash.substr(0, 16)])
# 运行结果: 打印资源路径和哈希前 16 位
func verify_asset(asset_path: String) -> bool:
if not _asset_hashes.has(asset_path):
return false
var file = FileAccess.open(asset_path, FileAccess.READ)
if file == null:
return false
var data = file.get_buffer(file.get_length())
file.close()
var current_hash = data.sha256_string()
var valid = current_hash == _asset_hashes[asset_path]
print("资源验证 %s:%s" % [asset_path, "完整" if valid else "已损坏"])
# 运行结果: 文件完整打印"完整",否则打印"已损坏"
return valid注意事项
- 比 MD5 更安全:SHA-256 输出 256 位(64 个十六进制字符),碰撞概率远低于 MD5(128 位/32 字符)。适合需要更高安全性的场景。
- 仍然是单向的:和 MD5 一样,SHA-256 也是不可逆的——无法从哈希值还原原始内容。
- C# 中使用 .NET 标准库:C# 没有 Godot 内置的
Sha256Text()方法,需要使用System.Security.Cryptography.SHA256。 - 密码存储推荐加盐:直接对密码做 SHA-256 仍然不够安全(容易被彩虹表攻击)。应该为每个密码生成一个随机的"盐值",将盐值和密码拼接后再哈希。
- 性能比 MD5 稍慢:SHA-256 的计算比 MD5 稍慢,但对游戏中的使用场景来说差异可以忽略不计。
