Skip to content

Commit

Permalink
fix(k8s): add ToValidRFC1123String
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Aug 10, 2023
1 parent e2efb32 commit d6d6f09
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/GZCTF/Models/Data/Challenge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ internal string GenerateFlag(Participation part)
// for third-party flag calculation and external distribution.
// To address this issue, one possible solution is to use a salted hash of
// the private key as the salt for the team's hash.
var hash = Codec.StrSHA256($"{part.Token}::{part.Game.TeamHashSalt}::{Id}");
var hash = $"{part.Token}::{part.Game.TeamHashSalt}::{Id}".StrSHA256();
return flag.Replace("[TEAM_HASH]", hash[12..24]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/GZCTF/Models/Data/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public class Game
public string? PosterUrl => PosterHash is null ? null : $"/assets/{PosterHash}/poster";

[NotMapped]
public string TeamHashSalt => Codec.StrSHA256($"GZCTF@{PrivateKey}@PK");
public string TeamHashSalt => $"GZCTF@{PrivateKey}@PK".StrSHA256();

internal void GenerateKeyPair(byte[]? xorkey)
{
Expand Down
2 changes: 1 addition & 1 deletion src/GZCTF/Models/Data/Post.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ internal Post Update(PostEditModel model, UserInfo user)
return this;
}

internal void UpdateKeyWithHash() => Id = Codec.StrSHA256($"{Title}:{UpdateTimeUTC:s}:{Guid.NewGuid()}")[4..12];
internal void UpdateKeyWithHash() => Id = $"{Title}:{UpdateTimeUTC:s}:{Guid.NewGuid()}".StrSHA256()[4..12];
}
2 changes: 1 addition & 1 deletion src/GZCTF/Services/DockerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public async Task DestroyContainerAsync(Container container, CancellationToken t
}

private static string GetName(ContainerConfig config)
=> $"{config.Image.Split("/").LastOrDefault()?.Split(":").FirstOrDefault()}_{Codec.StrMD5(config.Flag ?? Guid.NewGuid().ToString())[..16]}";
=> $"{config.Image.Split("/").LastOrDefault()?.Split(":").FirstOrDefault()}_{(config.Flag ?? Guid.NewGuid().ToString()).StrMD5()[..16]}";

private static CreateContainerParameters GetCreateContainerParameters(ContainerConfig config)
=> new()
Expand Down
13 changes: 3 additions & 10 deletions src/GZCTF/Services/K8sService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ public K8sService(IOptions<RegistryConfig> _registry, IOptions<ContainerProvider

if (withAuth)
{
var padding = Codec.StrMD5($"{registry.UserName}@{registry.Password}@{registry.ServerAddress}");
AuthSecretName = $"{registry.UserName}-{padding}";
var padding = $"{registry.UserName}@{registry.Password}@{registry.ServerAddress}".StrMD5();
AuthSecretName = $"{registry.UserName}-{padding}".ToValidRFC1123String("secret");
}

try
Expand All @@ -74,14 +74,7 @@ public K8sService(IOptions<RegistryConfig> _registry, IOptions<ContainerProvider
return null;
}

// add prefix when meet the leading numbers
// which is not allowed in k8s dns name
if (char.IsDigit(imageName[0]))
imageName = $"chal-{imageName}";

// follow the k8s naming convention
// use uuid to avoid name conflict
var name = $"{imageName}-{Guid.NewGuid().ToString("N")[..16]}".Replace('_', '-');
var name = $"{imageName.ToValidRFC1123String("chal")}-{Guid.NewGuid().ToString("N")[..16]}";

var pod = new V1Pod("v1", "Pod")
{
Expand Down
108 changes: 65 additions & 43 deletions src/GZCTF/Utils/Codec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,15 @@ public static string RandomPassword(int length)
return pwd;
}

/// <summary>
/// 转换为对应进制
/// </summary>
/// <param name="source">源数据</param>
/// <param name="tobase">进制支持2,8,10,16</param>
/// <returns></returns>
public static List<string> ToBase(List<int> source, int tobase)
=> new(source.ConvertAll((a) => Convert.ToString(a, tobase)));

/// <summary>
/// 字节数组转换为16进制字符串
/// </summary>
Expand Down Expand Up @@ -218,12 +227,62 @@ public static byte[] Xor(byte[] data, byte[] xor)
return res;
}

/// <summary>
/// 将文件打包为 zip 文件
/// </summary>
/// <param name="files">文件列表</param>
/// <param name="basepath">根目录</param>
/// <param name="zipName">压缩包根目录</param>
/// <param name="token"></param>
/// <returns></returns>
public async static Task<Stream> ZipFilesAsync(IEnumerable<LocalFile> files, string basepath, string zipName, CancellationToken token = default)
{
var size = files.Select(f => f.FileSize).Sum();

Stream tmp = size <= 64 * 1024 * 1024 ? new MemoryStream() :
File.Create(Path.GetTempFileName(), 4096, FileOptions.DeleteOnClose);

using var zip = new ZipArchive(tmp, ZipArchiveMode.Create, true);

foreach (var file in files)
{
var entry = zip.CreateEntry(Path.Combine(zipName, file.Name), CompressionLevel.Optimal);
await using var entryStream = entry.Open();
await using var fileStream = File.OpenRead(Path.Combine(basepath, file.Location, file.Hash));
await fileStream.CopyToAsync(entryStream, token);
}

await tmp.FlushAsync(token);
return tmp;
}
}

public static partial class CodecExtensions
{

[GeneratedRegex("[^a-zA-Z0-9]+")]
private static partial Regex RFC1123ReplacePattern();

/// <summary>
/// 将字符串转换为符合 RFC1123 要求的字符串
/// </summary>
/// <param name="str"></param>
/// <param name="leading">若开头为数字则添加的字符串</param>
/// <returns></returns>
public static string ToValidRFC1123String(this string str, string leading = "name")
{
var ret = RFC1123ReplacePattern().Replace(str, "-").Trim('-').ToLowerInvariant();
if (ret.Length > 0 && char.IsDigit(ret[0]))
return $"{leading}-{ret}";
return ret;
}

/// <summary>
/// 获取字符串ASCII数组
/// </summary>
/// <param name="str">原字符串</param>
/// <returns></returns>
public static List<int> ASCII(string str)
public static List<int> ASCII(this string str)
{
var buff = Encoding.ASCII.GetBytes(str);
List<int> res = new();
Expand All @@ -232,21 +291,12 @@ public static List<int> ASCII(string str)
return res;
}

/// <summary>
/// 转换为对应进制
/// </summary>
/// <param name="source">源数据</param>
/// <param name="tobase">进制支持2,8,10,16</param>
/// <returns></returns>
public static List<string> ToBase(List<int> source, int tobase)
=> new(source.ConvertAll((a) => Convert.ToString(a, tobase)));

/// <summary>
/// 反转字符串
/// </summary>
/// <param name="s">原字符串</param>
/// <returns></returns>
public static string Reverse(string s)
public static string Reverse(this string s)
{
var charArray = s.ToCharArray();
Array.Reverse(charArray);
Expand All @@ -259,7 +309,7 @@ public static string Reverse(string s)
/// <param name="str">原始字符串</param>
/// <param name="useBase64">是否使用Base64编码</param>
/// <returns></returns>
public static string StrMD5(string str, bool useBase64 = false)
public static string StrMD5(this string str, bool useBase64 = false)
{
var output = MD5.HashData(Encoding.Default.GetBytes(str));
if (useBase64)
Expand All @@ -273,7 +323,7 @@ public static string StrMD5(string str, bool useBase64 = false)
/// <param name="str">原始字符串</param>
/// <param name="useBase64">是否使用Base64编码</param>
/// <returns></returns>
public static string StrSHA256(string str, bool useBase64 = false)
public static string StrSHA256(this string str, bool useBase64 = false)
{
var output = SHA256.HashData(Encoding.Default.GetBytes(str));
if (useBase64)
Expand All @@ -286,43 +336,15 @@ public static string StrSHA256(string str, bool useBase64 = false)
/// </summary>
/// <param name="str">原始字符串</param>
/// <returns></returns>
public static byte[] BytesMD5(string str)
public static byte[] BytesMD5(this string str)
=> MD5.HashData(Encoding.Default.GetBytes(str));

/// <summary>
/// 获取SHA256哈希字节摘要
/// </summary>
/// <param name="str">原始字符串</param>
/// <returns></returns>
public static byte[] BytesSHA256(string str)
public static byte[] BytesSHA256(this string str)
=> SHA256.HashData(Encoding.Default.GetBytes(str));

/// <summary>
/// 将文件打包为 zip 文件
/// </summary>
/// <param name="files">文件列表</param>
/// <param name="basepath">根目录</param>
/// <param name="zipName">压缩包根目录</param>
/// <param name="token"></param>
/// <returns></returns>
public async static Task<Stream> ZipFilesAsync(IEnumerable<LocalFile> files, string basepath, string zipName, CancellationToken token = default)
{
var size = files.Select(f => f.FileSize).Sum();

Stream tmp = size <= 64 * 1024 * 1024 ? new MemoryStream() :
File.Create(Path.GetTempFileName(), 4096, FileOptions.DeleteOnClose);

using var zip = new ZipArchive(tmp, ZipArchiveMode.Create, true);

foreach (var file in files)
{
var entry = zip.CreateEntry(Path.Combine(zipName, file.Name), CompressionLevel.Optimal);
await using var entryStream = entry.Open();
await using var fileStream = File.OpenRead(Path.Combine(basepath, file.Location, file.Hash));
await fileStream.CopyToAsync(entryStream, token);
}

await tmp.FlushAsync(token);
return tmp;
}
}

0 comments on commit d6d6f09

Please sign in to comment.