封面图
玉清滴风小竹楼 玉清滴风小竹楼
今朝剑指叠云处

友链

先看效果,在浅色模式下:
在深色模式下:

P.S. 此算法只是尽可能地接近Windows Mica效果,并非实际实现;主色调提取算法只能确保在绝大多数情况下适用。

测试项目在Github上开源:
::github{repo="TwilightLemon/MicaImageTest"}

一、简要原理和设计 1.1 Mica效果

Mica效果是Windows 11的一个新特性,旨在为应用程序提供一种更柔和的背景效果。它通过使用桌面壁纸的颜色和纹理来创建一个静态的模糊背景效果。一个大致的模拟过程如下:

  1. 根据颜色模式(浅色或深色)来调整图像对比度
  2. 增加一个白色/黑色的遮罩层
  3. 大半径 高斯模糊处理

在仓库代码中给出了所有组件的实现,如果你想调整效果,可以修改以下几个值:

public static void ApplyMicaEffect(this Bitmap bitmap,bool isDarkmode)
{
    bitmap.AdjustContrast(isDarkmode?-1:-20);//Light Mode通常需要一个更高的对比度
    bitmap.AddMask(isDarkmode);//添加遮罩层
    bitmap.ScaleImage(2);//放大图像(原始图像一般为500x500)以提高输出图像质量
    var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    bitmap.GaussianBlur(ref rect, 80f, false);//按需要调整模糊半径
}
1.2 主色调提取与微调

从原始图像中提取主色调,主要过程如下:

  1. 像素采样和颜色量化便于统计
  2. 过滤过黑或过白的颜色值(我们会在调整步骤单独处理)
  3. 根据HSL的饱和度和亮度来计算权重,
    • 饱和度越高,权重越大
    • 亮度稳定(我们定为0.6),权重越大
  4. 选择权重最大的颜色均值作为主色调

之后为了适配UI,保证亮度、饱和度适合用于呈现内容,还要对颜色进行微调:

  1. 将颜色转为HSL空间
  2. 根据颜色模式调节亮度
  3. 分层调整饱和度,一般来说暗色模式的对比度比亮色模式高
  4. 对特定色相区间(红/绿/蓝/黄)进行差异化调整

最后计算焦点颜色(FocusAccentColor)只需要根据颜色模式调整亮度即可。

二、使用方法

将代码仓库中的ImageHelper.cs添加到项目,然后在需要的地方调用Bitmap的扩展方法来处理图像。以下是一个简单的示例:

首先开启项目允许使用UnSafe代码:

  <PropertyGroup>
    <!-- 允许使用UnSafe代码 -->
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>  

导入本地图像文件,计算主色调、焦点色调并应用Mica效果背景:

 var image=new BitmapImage(new Uri(ImagePath));
 SelectedImg = image;
 var bitmap = image.ToBitmap();
 //major color
 var majorColor = bitmap.GetMajorColor().AdjustColor(IsDarkMode);
 var focusColor = majorColor.ApplyColorMode(IsDarkMode);
 App.Current.Resources["AccentColor"] = new SolidColorBrush(majorColor);
 App.Current.Resources["FocusedAccentColor"] = new SolidColorBrush(focusColor);
 //background
 bitmap.ApplyMicaEffect(IsDarkMode);
 BackgroundImg = bitmap.ToBitmapImage();

其中,SelectedImgBackgroundImg是绑定到UI的BitmapImage类型属性,IsDarkMode是指示当前颜色模式的布尔值。

三、注意事项
  1. 处理大图像时可能会导致性能下降,建议使用较小的图像或在后台线程中处理。
  2. 如果高斯模糊组件报错,请确保Nuget包System.Drawing.Common的版本为8.0.1,因为代码中使用了反射获取Bitmap内部的句柄。
  3. 你可能需要根据实际情况调整模糊半径和对比度等参数,以获得最佳效果。
  4. 库中实现可能并非最佳写法,如果有更好的方法可以提交PR或者评论区见。

最后附上ImageHelper.cs的完整代码

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;

namespace MicaImageTest;

public static class ImageHelper
{
    #region 处理模糊图像
    [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int GdipBitmapApplyEffect(IntPtr bitmap, IntPtr effect, ref Rectangle rectOfInterest, bool useAuxData, IntPtr auxData, int auxDataSize);
    /// <summary>
    /// 获取对象的私有字段的值
    /// </summary>
    /// <typeparam name="TResult">字段的类型</typeparam>
    /// <param name="obj">要从其中获取字段值的对象</param>
    /// <param name="fieldName">字段的名称.</param>
    /// <returns>字段的值</returns>
    /// <exception cref="System.InvalidOperationException">无法找到该字段.</exception>
    /// 
    internal static TResult GetPrivateField<TResult>(this object obj, string fieldName)
    {
        if (obj == null) return default(TResult);
        Type ltType = obj.GetType();
        FieldInfo lfiFieldInfo = ltType.GetField(fieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
        if (lfiFieldInfo != null)
            return (TResult)lfiFieldInfo.GetValue(obj);
        else
            throw new InvalidOperationException(string.Format("Instance field '{0}' could not be located in object of type '{1}'.", fieldName, obj.GetType().FullName));
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct BlurParameters
    {
        internal float Radius;
        internal bool ExpandEdges;
    }
    [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int GdipCreateEffect(Guid guid, out IntPtr effect);
    private static Guid BlurEffectGuid = new Guid("{633C80A4-1843-482B-9EF2-BE2834C5FDD4}");
    [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int GdipSetEffectParameters(IntPtr effect, IntPtr parameters, uint size);
    public static IntPtr NativeHandle(this Bitmap Bmp)
    {
        // 通过反射获取Bitmap的私有字段nativeImage的值,该值为GDI+的内部图像句柄
        //新版(8.0.1)Drawing的Nuget包中字段由 nativeImage变更为_nativeImage
        return Bmp.GetPrivateField<IntPtr>("_nativeImage");
    }
    [DllImport("gdiplus.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int GdipDeleteEffect(IntPtr effect);
    public static void GaussianBlur(this Bitmap Bmp, ref Rectangle Rect, float Radius = 10, bool ExpandEdge = false)
    {
        int Result;
        IntPtr BlurEffect;
        BlurParameters BlurPara;
        if ((Radius < 0) || (Radius > 255))
        {
            throw new ArgumentOutOfRangeException("半径必须在[0,255]范围内");
        }
        BlurPara.Radius = Radius;
        BlurPara.ExpandEdges = ExpandEdge;
        Result = GdipCreateEffect(BlurEffectGuid, out BlurEffect);
        if (Result == 0)
        {
            IntPtr Handle = Marshal.AllocHGlobal(Marshal.SizeOf(BlurPara));
            Marshal.StructureToPtr(BlurPara, Handle, true);
            GdipSetEffectParameters(BlurEffect, Handle, (uint)Marshal.SizeOf(BlurPara));
            GdipBitmapApplyEffect(Bmp.NativeHandle(), BlurEffect, ref Rect, false, IntPtr.Zero, 0);
            // 使用GdipBitmapCreateApplyEffect函数可以不改变原始的图像,而把模糊的结果写入到一个新的图像中
            GdipDeleteEffect(BlurEffect);
            Marshal.FreeHGlobal(Handle);
        }
        else
        {
            throw new ExternalException("不支持的GDI+版本,必须为GDI+1.1及以上版本,且操作系统要求为Win Vista及之后版本.");
        }
    }
    #endregion

    public static System.Windows.Media.Color GetMajorColor(this Bitmap bitmap)
    {
        int skip = Math.Max(1, Math.Min(bitmap.Width, bitmap.Height) / 100);

        Dictionary<int, ColorInfo> colorMap = [];
        int pixelCount = 0;

        for (int h = 0; h < bitmap.Height; h += skip)
        {
            for (int w = 0; w < bitmap.Width; w += skip)
            {
                Color pixel = bitmap.GetPixel(w, h);

                // 量化颜色 (减少相似颜色的数量)
                int quantizedR = pixel.R / 16 * 16;
                int quantizedG = pixel.G / 16 * 16;
                int quantizedB = pixel.B / 16 * 16;

                // 排除极端黑白色
                int averange = (pixel.R + pixel.G + pixel.B) / 3;
                if (averange < 24) continue;
                if (averange > 230) continue;

                int colorKey = (quantizedR << 16) | (quantizedG << 8) | quantizedB;

                if (colorMap.TryGetValue(colorKey, out ColorInfo info))
                {
                    info.Count++;
                    info.SumR += pixel.R;
                    info.SumG += pixel.G;
                    info.SumB += pixel.B;
                }
                else
                {
                    colorMap[colorKey] = new ColorInfo
                    {
                        Count = 1,
                        SumR = pixel.R,
                        SumG = pixel.G,
                        SumB = pixel.B
                    };
                }
                pixelCount++;
            }
        }

        if (pixelCount == 0 || colorMap.Count == 0)
            return System.Windows.Media.Colors.Gray;

        var weightedColors = colorMap.Values.Select(info =>
        {
            float r = info.SumR / (float)info.Count / 255f;
            float g = info.SumG / (float)info.Count / 255f;
            float b = info.SumB / (float)info.Count / 255f;

            // 转换为HSL来检查饱和度和亮度
            RgbToHsl(r, g, b, out float h, out float s, out float l);

            // 颜色越饱和越有可能是主色调,过亮或过暗的颜色权重降低
            float weight = info.Count * s * (1 - Math.Abs(l - 0.6f) * 1.8f);

            return new
            {
                R = info.SumR / info.Count,
                G = info.SumG / info.Count,
                B = info.SumB / info.Count,
                Weight = weight
            };
        })
        .OrderByDescending(c => c.Weight);

        if (weightedColors.First() is { } dominantColor)
        {
            // 取权重最高的颜色
            return System.Windows.Media.Color.FromRgb(
                (byte)dominantColor.R,
                (byte)dominantColor.G,
                (byte)dominantColor.B);
        }

        return System.Windows.Media.Colors.Gray;
    }

    private class ColorInfo
    {
        public int Count { get; set; }
        public int SumR { get; set; }
        public int SumG { get; set; }
        public int SumB { get; set; }
    }

    public static System.Windows.Media.Color AdjustColor(this System.Windows.Media.Color col, bool isDarkMode)
    {
        // 转换为HSL色彩空间,便于调整亮度和饱和度
        RgbToHsl(col.R / 255f, col.G / 255f, col.B / 255f, out float h, out float s, out float l);

        bool isNearGrayscale = s < 0.15f; // 判断是否接近灰度

        // 1. 基于UI模式进行初步亮度调整
        if (isDarkMode)
        {
            // 在暗色模式下,避免颜色过暗,提高整体亮度
            if (l < 0.5f)
                l = 0.3f + l * 0.5f;

            if (isNearGrayscale)
                l = Math.Max(l, 0.4f); // 确保足够明亮
        }
        else
        {
            // 在亮色模式下,避免颜色过亮,降低整体亮度
            if (l > 0.5f)
                l = 0.3f + l * 0.4f;

            if (isNearGrayscale)
                l = Math.Min(l, 0.6f); // 确保不过亮
        }

        // 2. 调整饱和度
        if (!isNearGrayscale)
        {
            if (s > 0.7f)
            {
                // 高饱和度降低,但是暗色模式需要更鲜明的颜色
                s = isDarkMode ? 0.7f - (s - 0.7f) * 0.2f : 0.65f - (s - 0.7f) * 0.4f;
            }
            else if (s > 0.4f)
            {
                // 中等饱和度微调
                s = isDarkMode ? s * 0.85f : s * 0.75f;
            }
            else if (s > 0.1f) // 低饱和度但不是接近灰度
            {
                // 低饱和度增强,尤其在暗色模式下
                s = isDarkMode ? Math.Min(0.5f, s * 1.5f) : Math.Min(0.4f, s * 1.3f);
            }
        }

        // 3. 特殊色相区域的处理
        if (!isNearGrayscale) // 仅处理有明显色相的颜色
        {
            // 红色区域 (0-30° 或 330-360°)
            if ((h <= 0.08f) || (h >= 0.92f))
            {
                if (isDarkMode)
                {
                    // 暗色模式下红色需要更高饱和度和亮度
                    s = Math.Min(0.7f, s * 1.1f);
                    l = Math.Min(0.8f, l * 1.15f);
                }
                else
                {
                    // 亮色模式下红色降低饱和度,避免刺眼
                    s *= 0.8f;
                    l = Math.Max(0.4f, l * 0.9f);
                }
            }
            // 绿色区域 (90-150°)
            else if (h >= 0.25f && h <= 0.42f)
            {
                if (isDarkMode)
                {
                    // 暗色模式下绿色提高亮度,降低饱和度,避免荧光感
                    s *= 0.85f;
                    l = Math.Min(0.7f, l * 1.2f);
                }
                else
                {
                    // 亮色模式下绿色降低饱和度更多
                    s *= 0.75f;
                }
            }
            // 蓝色区域 (210-270°)
            else if (h >= 0.58f && h <= 0.75f)
            {
                if (isDarkMode)
                {
                    // 暗色模式下蓝色提高亮度和饱和度
                    s = Math.Min(0.85f, s * 1.2f);
                    l = Math.Min(0.7f, l * 1.25f);
                }
                else
                {
                    // 亮色模式下蓝色保持中等饱和度
                    s = Math.Min(0.7f, Math.Max(0.4f, s));
                }
            }
            // 黄色区域 (30-90°)
            else if (h > 0.08f && h < 0.25f)
            {
                if (isDarkMode)
                {
                    // 暗色模式下黄色需要降低饱和度,提高亮度
                    s *= 0.8f;
                    l = Math.Min(0.75f, l * 1.2f);
                }
                else
                {
                    // 亮色模式下黄色大幅降低饱和度
                    s *= 0.7f;
                    l = Math.Max(0.5f, l * 0.9f);
                }
            }
        }



        // 5. 最终亮度修正 - 确保在各种UI模式下都有足够的对比度
        if (isDarkMode && l < 0.3f) l = 0.3f; // 暗色模式下确保最小亮度
        if (!isDarkMode && l > 0.7f) l = 0.7f; // 亮色模式下确保最大亮度

        // 转换回RGB
        HslToRgb(h, s, l, out float r, out float g, out float b);

        // 确保RGB值在有效范围内
        byte R = (byte)Math.Max(0, Math.Min(255, r * 255));
        byte G = (byte)Math.Max(0, Math.Min(255, g * 255));
        byte B = (byte)Math.Max(0, Math.Min(255, b * 255));

        return System.Windows.Media.Color.FromRgb(R, G, B);
    }
    public static System.Windows.Media.Color ApplyColorMode(this System.Windows.Media.Color color,bool isDarkMode)
    {
        RgbToHsl(color.R/255f,color.G/255f, color.B/255f,out float h, out float s, out float l);
        if (isDarkMode)
            l = Math.Max(0.05f, l - 0.1f);
        else
            l = Math.Min(0.95f, l + 0.1f);

        HslToRgb(h, s, l, out float r, out float g, out float b);
        return System.Windows.Media.Color.FromRgb((byte)(r * 255), (byte)(g * 255), (byte)(b * 255));
    }

    private static void RgbToHsl(float r, float g, float b, out float h, out float s, out float l)
    {
        float max = Math.Max(r, Math.Max(g, b));
        float min = Math.Min(r, Math.Min(g, b));

        // 计算亮度
        l = (max + min) / 2.0f;

        // 默认值初始化
        h = 0;
        s = 0;

        if (max == min)
        {
            // 无色调 (灰色)
            return;
        }

        float d = max - min;

        // 计算饱和度
        s = l > 0.5f ? d / (2.0f - max - min) : d / (max + min);

        // 计算色相
        if (max == r)
        {
            h = (g - b) / d + (g < b ? 6.0f : 0.0f);
        }
        else if (max == g)
        {
            h = (b - r) / d + 2.0f;
        }
        else // max == b
        {
            h = (r - g) / d + 4.0f;
        }

        h /= 6.0f;

        // 确保h在[0,1]范围内
        h = Math.Max(0, Math.Min(1, h));
    }

    private static void HslToRgb(float h, float s, float l, out float r, out float g, out float b)
    {
        // 确保h在[0,1]范围内
        h = ((h % 1.0f) + 1.0f) % 1.0f;

        // 确保s和l在[0,1]范围内
        s = Math.Max(0, Math.Min(1, s));
        l = Math.Max(0, Math.Min(1, l));

        if (s == 0.0f)
        {
            // 灰度颜色
            r = g = b = l;
            return;
        }

        float q = l < 0.5f ? l * (1.0f + s) : l + s - l * s;
        float p = 2.0f * l - q;

        r = HueToRgb(p, q, h + 1.0f / 3.0f);
        g = HueToRgb(p, q, h);
        b = HueToRgb(p, q, h - 1.0f / 3.0f);
    }

    private static float HueToRgb(float p, float q, float t)
    {
        // 确保t在[0,1]范围内
        t = ((t % 1.0f) + 1.0f) % 1.0f;

        if (t < 1.0f / 6.0f)
            return p + (q - p) * 6.0f * t;
        if (t < 0.5f)
            return q;
        if (t < 2.0f / 3.0f)
            return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
        return p;
    }
    public static BitmapImage ToBitmapImage(this Bitmap Bmp)
    {
        BitmapImage BmpImage = new();
        using (MemoryStream lmemStream = new())
        {
            Bmp.Save(lmemStream, ImageFormat.Png);
            BmpImage.BeginInit();
            BmpImage.StreamSource = new MemoryStream(lmemStream.ToArray());
            BmpImage.EndInit();
        }
        return BmpImage;
    }

    public static Bitmap ToBitmap(this BitmapImage img){
        using MemoryStream outStream = new();
        BitmapEncoder enc = new PngBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(img));
        enc.Save(outStream);
        return new Bitmap(outStream);
    }

    public static void AddMask(this Bitmap bitmap,bool darkmode)
    {
        var color1 = darkmode ? Color.FromArgb(150, 0, 0, 0) : Color.FromArgb(160, 255, 255, 255);
        var color2 = darkmode ? Color.FromArgb(180, 0, 0, 0) : Color.FromArgb(200, 255, 255, 255);
        using Graphics g = Graphics.FromImage(bitmap);
        using LinearGradientBrush brush = new(
            new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            color1,
            color2,
            LinearGradientMode.Vertical);
        g.FillRectangle(brush, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
    }
    public static void AdjustContrast(this Bitmap bitmap, float contrast)
    {
        contrast = (100.0f + contrast) / 100.0f;
        contrast *= contrast;

        BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadWrite, bitmap.PixelFormat);

        int width = bitmap.Width;
        int height = bitmap.Height;

        unsafe
        {
            for (int y = 0; y < height; y++)
            {
                byte* row = (byte*)data.Scan0 + (y * data.Stride);
                for (int x = 0; x < width; x++)
                {
                    int idx = x * 3;

                    float blue = row[idx] / 255.0f;
                    float green = row[idx + 1] / 255.0f;
                    float red = row[idx + 2] / 255.0f;

                    // 转换为HSL
                    RgbToHsl(red, green, blue, out float h, out float s, out float l);

                    // 调整亮度以增加对比度
                    l = (((l - 0.5f) * contrast) + 0.5f);

                    // 转换回RGB
                    HslToRgb(h, s, l, out red, out green, out blue);

                    row[idx] = (byte)Math.Max(0, Math.Min(255, blue * 255.0f));
                    row[idx + 1] = (byte)Math.Max(0, Math.Min(255, green * 255.0f));
                    row[idx + 2] = (byte)Math.Max(0, Math.Min(255, red * 255.0f));
                }
            }
        }

        bitmap.UnlockBits(data);
    }

    public static void ScaleImage(this Bitmap bitmap, double scale)
    {
        // 计算新的尺寸
        int newWidth = (int)(bitmap.Width * scale);
        int newHeight = (int)(bitmap.Height * scale);

        // 创建目标位图
        Bitmap newBitmap = new Bitmap(newWidth, newHeight, bitmap.PixelFormat);

        // 设置高质量绘图参数
        using (Graphics graphics = Graphics.FromImage(newBitmap))
        {
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

            // 绘制缩放后的图像
            graphics.DrawImage(bitmap,
                new Rectangle(0, 0, newWidth, newHeight),
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                GraphicsUnit.Pixel);
        }
        bitmap = newBitmap;
    }

    public static void ApplyMicaEffect(this Bitmap bitmap,bool isDarkmode)
    {
        bitmap.AdjustContrast(isDarkmode?-1:-20);
        bitmap.AddMask(isDarkmode);
        bitmap.ScaleImage(2);
        var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
        bitmap.GaussianBlur(ref rect, 80f, false);
    }
}

友链

Paper reference: Identity-Based Encryption from the Weil Pairing | SpringerLink

Known Public Encryption Scheme
  • Setup: Generate  global system parameters and a master-key

  • Extract: use the master-key to generate the private-key  corresponding to an public-key string $ID ∈ {0,1}^*$

  • Enc: encrypt M with ID → C

  • Dec: decrypt C with private-key

Application

(interesting)

Revocation of Public Keys

<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22215%22%2C%22position%22%3A%7B%22pageIndex%22%3A2%2C%22rects%22%3A%5B%5B149.70940037000003%2C484.58142187000004%2C480.66033437%2C494.54442187%5D%2C%5B134.76490037000002%2C472.62582187000004%2C480.61540123999987%2C482.58882187%5D%2C%5B134.76480073999997%2C460.67022187000003%2C261.2849377400001%2C470.63322187%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22215%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=3">“One could potentially make this approach more granular by encrypting e-mail for Bob using “bob@hotmail.com ‖ current-date”. This forces Bob to obtain a new private key every day.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22215%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/D9XP6B7N">Boneh and Franklin, p. 215</a></span>)</span>

<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22215%22%2C%22position%22%3A%7B%22pageIndex%22%3A2%2C%22rects%22%3A%5B%5B381.72764474%2C400.89222187%2C480.7399387399999%2C410.85522187%5D%2C%5B134.76480073999997%2C388.93662187%2C480.66023474%2C398.89962187%5D%2C%5B134.76480073999997%2C376.98102187%2C291.50271674%2C386.94402187%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22215%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=3">“This approach enables Alice to send messages into the future: Bob will only be able to decrypt the e-mail on the date specified by Alice”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22215%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/D9XP6B7N">Boneh and Franklin, p. 215</a></span>)</span>

Delegation of Decryption Keys
  1. bind <pk,sk> pairs with dates so that private-key can be stored in a vulnerable device: only thoses pairs are compromised and the Master-key is unharmed.
  2. delegations of duties or other title as a skill to distribute private keys.
Construction preparation Bilinear Map:  e.g. Weil pairing

$$ e: G_1 \times G_1 \rightarrow G_2 $$

, where $G_1$ and $G_2$ are two CYCLIC groups of some large prime order $p$ .

<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22216%22%2C%22position%22%3A%7B%22pageIndex%22%3A3%2C%22rects%22%3A%5B%5B175.40282900000003%2C431.93851%2C480.096666%2C442.64928%5D%2C%5B134.765%2C418.29671934000004%2C480.64607099999995%2C432.06751%5D%2C%5B134.75561850000005%2C408.02853%2C264.157754%2C418.73827%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22216%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=4">“In our system, G1 is the group of points of an elliptic curve over Fp and G2 is a subgroup of F∗p2 . Therefore, we view G1 as an additive group and G2 as a multiplicative group.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22216%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/D9XP6B7N">Boneh and Franklin, p. 216</a></span>)</span>

  • Bilinear $ e(aP,bQ) =e(P,Q)^{ab} ; for ; all ; P,Q∈G_1 ; and ; all ; a,b ∈ Z$

  • DH problem is hard in $G_1$

Properties of the Weil Pairing

Build:

$$ E:; y^2=x^3+1 ; over ; \mathbb{F}_p, $$

where prime $p$ satisfies $ p =2 ; (mod ; 3) ; and ; p=6q-1 ; for ; some ; prime ; q$

Syntax
  • Setup:  k -> sys param (publicly shared) | master key (owned by PKG (<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22216%22%2C%22position%22%3A%7B%22pageIndex%22%3A3%2C%22rects%22%3A%5B%5B194.46929001%2C189.19395407000002%2C303.8032520100001%2C199.15695407%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22216%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=4">“Private Key Generator”</a></span> ))

  • **Extract(master-key K,string ID) **=> private decryption key d.> ID is used as a public key

  • Enc/Dec

Secure Models
  • IND-ID-CCA: <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22218%22%2C%22position%22%3A%7B%22pageIndex%22%3A5%2C%22rects%22%3A%5B%5B411.2665887000001%2C530.4193803699999%2C480.6289947000001%2C540.38238037%5D%2C%5B134.75348670000005%2C518.4637803699999%2C210.6615837000001%2C528.42678037%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22218%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=6">“adaptive chosen ciphertext attack”</a></span><span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22218%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/D9XP6B7N">Boneh and Franklin, p. 218</a></span>)</span>

  • ID-OWE(one-way encryption): Given random public key $K_{pub}$ and ciphertext C which is the encryption of a random message M using $K_{pub}$ , A’s goal is to recover M.

models above allow A to conduct multi-round queries of <ID,d(private key)> pairs;

Scheme MapToPoint(string ID)=> Point

$G: ; {0,1}^* \rightarrow \mathbb{F}_b$ , where in the security analysis  G is viewed as a random oracle.

  1. Compute $ y_0 = G(ID)$  and $ y_0 \rightarrow E:;x_0=(y^2_0 -1)^{1/3} =(y^2_0-1)^{(2p-1)/3};mod;p$

  2. return $Q_{ID} = 6(x_0,y_0) ∈ E/\mathbb{F}_b$

Basic IBE (BasicIdent)

security parameter: $k$

Setup

Step 1: Choose a large k-bit prime p such that p = 2 mod 3 and p = 6q − 1 for some prime q > 3. Let E be the elliptic curve defined by $y^2 = x^3 + 1$  over $\mathbb{F}_b$ . Choose an arbitrary $P ∈ E/\mathbb{F}_p$  of order q.

Step 2: Pick a random $s ∈ Z^*q$  and set $P{pub} = sP$ .

Step 3: Choose a cryptographic hash function $H: ; F_{p^2} → {0, 1}^n$  for some n. Choose a cryptographic hash function $G: ; {0, 1}^∗ → \mathbb{F}_p$. The security analysis will view H and G as random oracles.

output: system params :=$<p,n,P,P_{pub},G,H>$ , master-key : $s∈\mathbb{Z}_q$ picked in Step 2.

Message space is $ M ={0,1}^n$

Ciphertext space is $ C= E/\mathbb{F}_b \times {0,1}^n$

Extract(string ID)

Step 1. $ Q_{ID} = MapToPoint(ID)$

Step 2. private key $d_{ID}=sQ_{ID}$, where s is the master key.

Encrypt

$$ Q_{ID} = MapToPoint(ID) $$

$$ r \xleftarrow{\text$} \mathbb{Z}_q $$

$$ C=<rP,M \oplus H(g^r_{ID})> ; where ; g_{ID}=e(Q_{ID},P_{pub}) $$

Decrypt

<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FBQTNBP2M%22%2C%22pageLabel%22%3A%22222%22%2C%22position%22%3A%7B%22pageIndex%22%3A9%2C%22rects%22%3A%5B%5B182.47192882999997%2C546.8013%2C480.63134203999965%2C556.7643%5D%2C%5B143.26931716999997%2C534.09952%2C480.59374037000003%2C544.80929%5D%2C%5B143.26549007000006%2C522.64177%2C339.58197999999993%2C532.85427%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22222%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/BQTNBP2M?page=10">“Let C = 〈U, V 〉 ∈ C be a ciphertext encrypted using the public key ID. If U ∈ E/Fp is not a point of order q reject the ciphertext. Otherwise, to decrypt C using the private key dID compute:”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FD9XP6B7N%22%5D%2C%22locator%22%3A%22222%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/D9XP6B7N">Boneh and Franklin, p. 222</a></span>)</span>

$$ M = V \oplus H(e(d_{ID},U)) $$

proof:

$$ e(d_{ID},U)=e(d_{ID},rP) =e(Q_{ID},P)^{sr} = e(Q_{ID},P_{pub}), ; where ; P_{pub}=sP ; is ; sys-param $$

IND-CCA Security: enhanced by Fujisaki-Okamoto transform Fujisaki-Okamoto transform

Suppose $<PEnc,PDec>$ is a public key encryption scheme.H and G are hash functions(viewed as random oracles): $ H: {0,1}^n \times {0,1}^n \rightarrow \mathbb{F}_q$ , $G: {0,1}^n \rightarrow {0,1}^n$

$$ \sigma \xleftarrow{\text$} Key ; Domain ; of ; H $$

$$ Enc_{FO}: C_K = PEnc(pk,\sigma; H(\sigma,M)) , ; C_M= G(\sigma) \oplus M $$

$$ Dec_{FO}: \sigma = PDec(sk,C_K), ; verify ; C_K == Enc_{FO}(·).C_K ; then ; M= C_M \oplus G(\sigma) $$

Comparing with conventional Hybrid Encryption, FO transform  surpasses as follows:

  • IND-CCA Security
  • using Hash functions to blind random seeds and message
  • check keys before decryption
Encrypt

$$ Q_{ID} = MapToPoint(ID) $$

$$ \sigma \xleftarrow{\text$} {0,1}^n, ; then ; r=H(\sigma,M) $$

$$ C=<rP,\sigma \oplus H(g^r_{ID}), M \oplus G(\sigma)> $$

Notice that $g^r_{ID} =e(Q_{ID,P_{pub}})^r$  binds with both the message M and the random seed $\sigma$ ,functioning as $H(\sigma,M)$ as that above.

Decrypt: receive C=<U,V,W>
  1. Check if $U ∈ E/\mathbb{F}_p$ is not a point of order q, otherwise reject C

  2. Compute $ \sigma = V \oplus H(e(d_{ID},U))$

  3. Decrypt $ M=W \oplus G(\sigma)$

  4. re-compute and check   $r=H(\sigma,M) == U =rP$

友链

Paper reference: Public Key Encryption with Keyword Search | SpringerLink

PEKS using Bilinear Maps Construction 素数p阶群, (乘法群)定义双线性映射:

非退化性:

  • $ e(g,g) \rightarrow g' , ; where ; g' ; is ; a ; generator ; of ; G_2$
Hash functions:
  • $ H_1: {0,1}^* \rightarrow G_1$
  • $ H_2 : G_2 \rightarrow {0,1}^{\log{p}}$
PEKS Scheme

$$ PEKS ; Scheme:=(KeyGen,PEKS,Trapdoor,Test) $$

KeyGen:

input 安全参数$\lambda$ , 群阶p, $G_1$ ,$G_2$ ,$$ \alpha \xleftarrow{\text$} Z^*_p$$, g是 $G_1$ 的一个生成元

output $ A_{pub} = [g,h=g^\alpha] ; and ; A_{priv} =\alpha$

一个典型的RSA公私钥分发

PEKS($A_{pub},W$):

$$ r \xleftarrow{\text$} Z^*_p$$ , then compute $ t = e(H_1(W),h^r)$

output $S=[g^r,H_2(t)]$

$ Trapdoor(A_{priv},W) => T_W =H_1(W)^\alpha$

Notice that $ t ∈ G_2$  and $ T_W ∈ G_1$

Test($A_{pub}$, S, $T_W$)

S=[A,B]

output $H_2(e(T_W,A)) == B$

proof:

$$ H_2(e(T_W,A)) = H_2(e(H_1(W)^\alpha,g^r)) = H_2(e(H_1(W),g)^{\alpha r}) $$

$$ H_2(t) = H_2(e(H_1(W),h^r)) = H_2(e(H_1(W),g^{\alpha r}))= H_2(e(H_1(W),g)^{\alpha r}) $$

BDH Assumption

<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2F263DSXDA%22%2C%22pageLabel%22%3A%22512%22%2C%22position%22%3A%7B%22pageIndex%22%3A6%2C%22rects%22%3A%5B%5B134.76133%2C350.8833972%2C480.50933480000003%2C360.5445306%5D%2C%5B134.76129%2C339.0033972%2C480.6450542%2C350.71035%5D%2C%5B134.76151%2C327.0033972%2C480.55128557999967%2C336.66458059999997%5D%2C%5B134.7604%2C315.9373418%2C296.1176583800001%2C324.78413059999997%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FKYUKPHCB%22%5D%2C%22locator%22%3A%22512%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/263DSXDA?page=7">“Bilinear Diffie-Hellman Problem (BDH): Fix a generator g of G1. The BDH problem is as follows: given g, ga, gb, gc ∈ G1 as input, compute e(g, g)abc ∈ G2. We say that BDH is intractable if all polynomial time algorithms have a negligible advantage in solving BDH.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FKYUKPHCB%22%5D%2C%22locator%22%3A%22512%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/KYUKPHCB">Boneh et al., 2004, p. 512</a></span>)</span>

安全性证明 定理1. 非交互式PEKS在适应性选择关键词攻击下具有语义安全,如果BDH是难解问题。
  • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">安全目标</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">:在自适应选择关键词攻击下语义安全。</span></span>

  • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">归约到BDH问题</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">:</span></span>

    • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">假设存在攻击者 </span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">A</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 能以优势 </span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">ϵ</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 区分关键词加密,构造算法 </span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">B</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 利用 </span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">A</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 解决BDH问题。</span></span>

    • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">模拟过程</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">:</span></span>

      1. <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">B</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 接收BDH挑战 </span></span> $(g,g^α,g^β,g^γ)$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">,模拟公钥 </span></span> $h=g^α$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">。</span></span>

      2. <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">对 </span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">A</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 的陷门查询,若关键词关联 </span></span> $g^β$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">,则终止;否则返回合法陷门。</span></span>

      3. <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">挑战阶段,随机选择 </span></span> $W^b$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​,构造密文 </span></span> $(g^γ,H_2​(e(g^β,g^{αγ})))$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">。</span></span>

      4. <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">攻击者成功时,</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">B</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 从哈希列表提取</span></span> $ e(g,g)^{αβγ}$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">。</span></span>

  • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">优势分析</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">:</span></span>

    • <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">B</span></span><span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)"> 的成功概率为 </span></span> $ ϵ/(e \cdot q_T \cdot ​q_{H_2}​​ ) $ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">,其中 </span></span> $q_T$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​ 为陷门查询次数,</span></span> $q_{H_2}$ <span style="color: rgba(255, 255, 255, 0.9)"><span style="background-color: rgb(33, 33, 33)">​​ 为哈希查询次数。</span></span>

友链

Paper reference:

    Bin-linear Map

    <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22400%22%2C%22position%22%3A%7B%22pageIndex%22%3A4%2C%22rects%22%3A%5B%5B39.40400871913795%2C212.336551831%2C385.19543709878843%2C222.428273756752%5D%2C%5B39.4025698368481%2C200.375553295%2C385.2086489790012%2C211.0848576768476%5D%2C%5B39.402826538581394%2C189.57869231754017%2C108.45759041264529%2C198.51514429687816%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22400%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=5">“Suppose that G is an additive group of prime order p and GT is a multiplicative group of the same order. A bilinear map e : G × G → GT has the following three properties”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22400%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 400</a></span>)</span>

    Suppose $e$ is a map, e(param[] elements) is a function call.

    • Bio-linearThis means that e respects the group operations in both groups, i.e., it is linear in both arguments. The exponents a and b act multiplicatively on the map.

    • $ e(Q,R) \neq 1, for; all; Q,R∈G, Q \neq R $, where 1 denotes UNIT Element in Multiplicative Group.

    • e is effective to calcutale.

    MLE

    不用说懂得都懂

    SAS-MA

    Including 2 channels:

    • open channel<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22401%22%2C%22position%22%3A%7B%22pageIndex%22%3A5%2C%22rects%22%3A%5B%5B285.1118094399563%2C545.9691749927056%2C399.444596736801%2C554.9056269720436%5D%2C%5B53.57700598028832%2C534.0170440678318%2C399.4107235783859%2C542.9534960471698%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22401%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=6">“allows for transmission of messages of arbitrary length, but is subject to man-in-the-middle adversaries.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22401%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 401</a></span>)</span> Allow any ${0,1}^*$ messages; affacted by Man-in-the-middle Attack.

    • SAS channel<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22401%22%2C%22position%22%3A%7B%22pageIndex%22%3A5%2C%22rects%22%3A%5B%5B100.78179613468113%2C522.064913142958%2C361.072694015414%2C532.98743%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22401%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=6">“allows for transmission of up to t′-bit (e.g., 20-bit) messages”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22401%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 401</a></span>)</span> Allows for any ${0,1}^{t'}$ messages.(t' is a short interger, e.g. 20)

    “commitment“ is more alike a Hash sign of Message m for authentication.

    Threat Model
    • CS \ KS:  compromised<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22402%22%2C%22position%22%3A%7B%22pageIndex%22%3A6%2C%22rects%22%3A%5B%5B180.2653873864164%2C218.70994444120265%2C385.22794465299063%2C227.64639642054064%5D%2C%5B39.40319356190381%2C206.74884717655024%2C385.25783275250546%2C215.68529915588823%5D%2C%5B39.40319356190381%2C194.79671625167646%2C385.27178017554456%2C203.73316823101445%5D%2C%5B39.40319356190381%2C182.83561898702405%2C217.14593540814747%2C191.77207096636204%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22402%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=7">“An honest-but-curious cloud server may compromise the key servers to launch offline brute-force attacks and offline KGA against files and keywords, respectively. The number of compromised key servers is assumed to be less than the threshold.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22402%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 402</a></span>)</span>

    • Open Channel:

      • disclose pw & pw-derived sk
      • pw is low-entropy
      • A can reveal pw by existing <pw,sk> pairs
    • Trusted device owned by R

    cln. <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22403%22%2C%22position%22%3A%7B%22pageIndex%22%3A7%2C%22rects%22%3A%5B%5B211.08968652198027%2C436.32279462013236%2C399.4137058101841%2C445.2592465994704%5D%2C%5B66.5273830842246%2C424.37066369525854%2C362.8977894069446%2C433.30711567459656%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22403%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=8">“secure against an honest-but-curious cloud server, compromised key servers, and man-in-the-middle adversaries”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22403%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 403</a></span>)</span>

    Construction phase 1. ParaGen:
    • KS*n , 0<t<n : threshold

    • 素数p阶加法群G,生成元P;p阶乘法群GT

    • e双线性映射:e: G × G -> GT

    • Hash functions

      • H: *->G
      • h1: G&*->K(secure para.)
      • h2: GT->K
      • h3: *->K
      • h4: G&*->Zp*
    • 对称加密 SEnc\SDec

    • PKEnc\PKDec

    ServerSecretGen:

    KS 进行分布式密钥生成,产生α和β, and ones for their own.

    KS_i owns αi & βi.

    pk: V=α*P , Q=β*P and Vi Qi for KS_i of their own.

    <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22403%22%2C%22position%22%3A%7B%22pageIndex%22%3A7%2C%22rects%22%3A%5B%5B276.7322854886617%2C158.5250944621%2C399.4017761988422%2C168.4876942161%5D%2C%5B53.57602892379428%2C146.9724637873616%2C399.3748729756876%2C155.90891576669958%5D%2C%5B53.57603217160175%2C133.86554353%2C399.391125895123%2C144.57494664150002%5D%2C%5B53.57731896793456%2C121.91364686200001%2C399.4062014756252%2C132.6229498155%5D%2C%5B53.579466303985384%2C109.952648327%2C325.05115699337745%2C120.6619522565%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22403%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=8">“the key servers perform the distributed secret generation algorithm illustrated in Algorithm 1 twice to create two secrets α and β that are shared among them. Each key server KSi (i ∈ [n]) owns the secret shares αi and βi. The public keys V = α · P , Q = β · P and the public shares Vi = αi · P , Qi = βi · P for i ∈ [n] are published.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22403%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 403</a></span>)</span>

    运行算法两次得到的α和β分别用于File M和Keyword kw的签名

    Algorithm 1:

    实质是分布式密钥协商算法:

    The public key PK is shared and available, while each server only knows its own private share.

    prepare(input): 安全参数K, 大素数p, KS index 1~n, threshold t.

    P是 Zp*的生成元

    1. for every $KS_i$: , $$b_{i,0} \xleftarrow{\text$} Z^*p$$   $f_i(x) = poly_x: b{i,(0~t)}$

    2. for every $KS_i$: 计算$b_{i,(0~t-1)} \cdot P$  并公开,send $f_i(j)$  to every $KS_j$ now, for all $KS_i$  owns all KS's $b_{(index),(range: t)} \cdot P$> $b_{i,i} \cdot P$ :目的是盲化$b_i$

      threshold参数在$poly_x$上体现,只需要t个KS协作即可完成认证

    3. all trusted KS verifies: $ f_j(para: index)\cdot P == \sum_{n=0}^{t-1}{i^n \cdot b_{j,n}} $> 确保得到的$b_i$与$KS_i$所声明的一致(在KS群中保持一致,不可能存在一个腐败的KS,除非所有KS都欺骗Server)

    4. $KS_i$: 计算 $s_i = \sum_{q=1}^n{f_q(para:i)}$
      $PK_i$ = $s_i \cdot P$ \\升阶(群内)盲化

    5. for all KS: 协商获得 pk: $PK=\sum_{q=1}^{n}{b_{q,0} \cdot P}$

    OUTPUT:

    PK | {$PK_i ; for; every; KS_i$}

    (${s_i}$ are stored inside KS as secure key)

    $s_i,; α_i,; β_i$

    use $PK_i (aka. ; V_i ; Q_i); to ; verify ; sign ; σ'_i$

    ReceiverKeyGen:

    k∈Zp* randomly (在device D中储存)

    $$ \gamma = h_4(k \cdot H(pw) || pw ) , \Gamma = \gamma \cdot P $$

    (<span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22404%22%2C%22position%22%3A%7B%22pageIndex%22%3A8%2C%22rects%22%3A%5B%5B67.99864627306988%2C371.180908692414%2C216.33279033116298%2C380.117360671752%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22404%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=9">“the password-derived public key Γ”</a></span> )

    γ是私钥,Γ是公钥  used in PKEnc\PKDec

    phase 2. MLEKey & sdk(server-derived key) Gen:

    prepare: File M and its Keywords {w_j} T=|{wj}|

    1. $$ r' ; and ; {r_j} \xleftarrow{\text{$}} Z^*_p ;,; T=|{r_j}| $$ $M’ = r’ \cdot H(M)$    文件HASH盲化
      $w’_j=r_j \cdot H(w_j)$   Keyword hash盲化

    2. 共享 M’ 与 ${w’_j}$ with All KS

    3. for $KS_i$: Sign “the signatures $σ'i = α_i \cdot M' ; and ; δ{i',j} = β_i · w'_j ; for ; j = 1, 2, · · · , T .$ These signatures will be transmitted to S”

    4. Server verifies signs

      $$ e(σ’i,P)==e(M’,Vi); and ; e(δ’{i,j},P) ==e(w’_j,Q_i) $$

    补充知识:

    BLS签名的基本步骤
    1. 密钥生成

      • 选择一个椭圆曲线群 G 和双线性映射e

        $$ e: G \times G \rightarrow G_T $$

      • 生成私钥$x \in \mathbb{Z}_q$(一个随机数,q 是群的阶)。

      • 计算公钥 $P = x \cdot G$ ,其中 G 是基点。

    2. 签名生成

      • 对消息 m 进行哈希处理,得到 H(m),这里 H(m)是一个映射到椭圆曲线的点。

      • 使用私钥 x对 H(m) 进行签名:签名

        $$ \sigma = x \cdot H(m) $$

    3. 签名验证

      • 验证者首先计算 H(m) 并得到消息的哈希值。

      • 使用公钥 P 和签名 σ 进行验证:检查是否满足以下等式:

        $$ e(\sigma, G) = e(H(m), P) $$

      • 如果该等式成立,则签名是有效的,否则无效。

    4. 正确性验证(双线性):

      $$ \sigma = x \cdot H(m)
      $$

    $$ P = x \cdot G
    $$

    $$

    e(\sigma.G) = e(H(m),G)^x $$

    $$ e(H(m),P) = e(H(m),G)^x $$

    拉格朗日插值(Lagrange Interpolation)

    是一种多项式插值方法,用于通过已知的离散数据点($x_i, y_i$​)构建一个多项式,该多项式通过这些数据点。具体来说,给定 n+1 个数据点 $(x_0, y_0), (x_1, y_1), \dots, (x_n, y_n)$,拉格朗日插值通过构造一个多项式 L(x),使得:

    $$ L(x_i) = y_i, \quad \forall i = 0, 1, \dots, n $$

    拉格朗日插值公式为:

    $$ L(x) = \sum_{i=0}^{n} y_i \cdot \ell_i(x) $$

    其中,$\ell_i(x)$ 为第 i 个基拉格朗日多项式,其定义为:

    $$ \ell_i(x) = \prod_{\substack{0 \leq j \leq n \ j \neq i}} \frac{x - x_j}{x_i - x_j} $$

    这意味着每个基多项式  $ell_i(x)$ 在 $x_i$ 处为1,其他数据点处为0。最终,L(x) 就是通过所有数据点的加权组合。

    Encryption
    1. 使用MLE Key $ek_M$对称加密M:

      $$ C_M = SEnc(ek_M,M). $$

    2. Γ是用户的pw-derived pk,公钥加密MLE KEY:

      $$ C_{ek_M} = PKEnc(\Gamma,ek_M) $$

    3. 加密server-derived keywords , ξj 从Zp*中随机选取:

      $$ C_{sdk_wj} = (\xi_j \cdot P, h_2(\tau_j)) $$

      $$ where, \tau_j = e(H(sdk_{w_k},\xi_j \cdot \Gamma)) $$

    OUT SOURCE: $C_M$ , $C_(ek_M)$, ${C_(sdk_wj)}$ for j∈[T]

    De-duplication

    package:

    $$ L_R := (Ind_{M^}, C_{eK_{M^}}, {C_{sdk_{w^*_j}}} ) $$

    $$ L_G ={ Ind_M*, X_M*, C_M*} ; where, X_M* = h_3(C_m*) $$

    phase 3. Data Access R: Key Recovery (SAS-MA)

    $input: pw \quad output: private-key ; \gamma$

    1. Client  interact with Device:

      $$ r ∈ Z^*_p , ; z∈{0,1}^K, ; R_c ∈ {0,1}^{t'} $$

      $$ 盲化 pw'=r \cdot H(pw), ; Com=h_3(pw' || R_c||z) $$

      $$ pw'; and ;Com → D $$

      $$ D: R_D ∈ {0,1}^{t'} → Client $$

      $$ C: \Phi_C = R_C \oplus R_D ; send; (R_C,z) ;to ;D $$

      在SAS信道中(C TO D):

      $$ \Phi_C = R_C \oplus R_D $$

      D 计算 checksum

      $$ \Phi_D =R_C \oplus R_D ; == \Phi_C $$

      检查承诺

      $$ Com == h_3(pw'||R_C||Z) $$

      成功则进行(实质是一个同态加密,pw经过盲化,只传输并操作pw’,C拥有盲化因子, k是Device拥有的私钥)并 send to C:

      $$ v'= k \cdot pw' $$

      C 解盲化并得到私钥γ

      $$ v=r^{-1} \cdot v' ; and ; private-key ; \gamma = h_4(v||pw) $$

      即得到私钥 $\gamma = h_4(k \cdot H(pw) || pw )$

    Keyword Search

    $$ input:; keyword ;w^* $$

    1. Client interacts with KS to blinds w*, r*∈Zp*

      $$ W^* = r^* \cdot H(w^*) ;→ ; KS $$

    2. For  $KS_i$ :

      $$ \xi'_i = \beta_i \cdot W^* ; → C $$

    3. Client Check  * threshold by:

      $$ e(\xi'_i,P) = e(W^*,Q_i) $$

      then computes:

      $$ \xi = r^{*-1} \sum_{n∈L}\lambda_n \xi'_n $$

      computes server-derived kw:

      $$ sdk_{w*} = h_1(\xi||w^*) $$

    4. $T_{sdk_{w^}} = \gamma \cdot H(sdk_{w^})$  send to CS

    5. query $L_R$ for $C_{sdk_w} =(A,B)$
      verify $h_2(e(T_{sdk_{w^*}},A)) == B$, where A is randomly selected by CS
      send (enc)MLE Key $C_{ek_M}$  (and $C_M$ ?) to C

    Decryption

    $ek_M = PKDec(\gamma,C_{ek_M}) → MLE ; Key$

    $ decrypts ; M=SDec(e_{k_M},C_M)$

    Security Proof 定理1. 如果使用盲BLS签名和SAS-MA,则DULCET是抗中间人攻击的

    <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22407%22%2C%22position%22%3A%7B%22pageIndex%22%3A11%2C%22rects%22%3A%5B%5B53.57699376294341%2C259.905737135855%2C399.433624012411%2C268.83222651543906%5D%2C%5B53.57699376294341%2C247.95360621098123%2C399.4027414712745%2C256.88009559056525%5D%2C%5B53.57699376294341%2C235.5740797566608%2C399.4024889076054%2C247.64235256299997%5D%2C%5B53.57774110636814%2C223.62231313662616%2C285.8597394107797%2C233.58491289062619%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22407%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=12">“Theorem 1. Assuming the blind BLS signature is of blindness and the short authentication string message authentication (SAS-MA) is secure, DULCET prevents a man-in-the-middle adversary A (e.g., CS∗) from learning the receiver R’s password-derived private key γ and password pw.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22407%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 407</a></span>)</span>

    security provided by:

    $$ private-key: ; \gamma = h_4(v||pw) $$

    $$ v= k \cdot H(pw) $$

    $$ where ; k \xleftarrow{\text{$}} Z^*_p ; in ; trusted ; device $$

    Blinded BLS signature & SAS-MA 保证k只在device中派生,不在任何信道中显式传输,对于一个外部敌手只能获得公钥并通过DGA来匹配pw:

    $$ public-key: ; \Gamma = \gamma \cdot P $$ ·

    定理2. 对于所有PPT敌手,DULCET是不可预测的

    <span class="highlight" data-annotation="%7B%22attachmentURI%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FA54BVCMA%22%2C%22pageLabel%22%3A%22408%22%2C%22position%22%3A%7B%22pageIndex%22%3A12%2C%22rects%22%3A%5B%5B39.40187341822877%2C425.9870362459722%2C385.23160427594865%2C435.9496359999722%5D%2C%5B39.4018715352974%2C414.0349053210984%2C337.14611965246513%2C423.9975050750984%5D%5D%7D%2C%22citationItem%22%3A%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22408%22%7D%7D" ztype="zhighlight"><a href="zotero://open/library/items/A54BVCMA?page=13">“Theorem 2. DULCET is of unpredictability if for any PPT adversary A, the advantage of A winning the unpredictability experiment is negligible.”</a></span> <span class="citation" data-citation="%7B%22citationItems%22%3A%5B%7B%22uris%22%3A%5B%22http%3A%2F%2Fzotero.org%2Fusers%2F16470860%2Fitems%2FJH5RQ343%22%5D%2C%22locator%22%3A%22408%22%7D%5D%2C%22properties%22%3A%7B%7D%7D" ztype="zcitation">(<span class="citation-item"><a href="zotero://select/library/items/JH5RQ343">Jiang et al., 2024, p. 408</a></span>)</span>

    在分布式密钥协商中,敌手最多能收集到t-1个子密钥(threshold t)

    $ Exp^{UDP}_{A,DULCET}(1^{\lambda}) $

    ...

    友链

    原论文地址:Password-Based Credentials with Security Against Server Compromise | SpringerLink

    四个安全目标:
    • 强不可伪造性:敌手A知道password并且服务器妥协,但不知道用户 ask (authenticated secret key),无法伪造验证令牌

    • 在线不可伪造性:A知道ask,服务器未妥协,则A只能通过在线猜测password来伪造令牌

      服务器可发现异常行为从而阻断

    • 离线不可伪造性:A知道ask,服务器妥协,则A能使用离线暴力猜测password

      使用强口令是最后一道防线

    • 口令隐藏性:服务器储存的avk(针对multi-key PBC 在服务器端储存的用户独有的验证凭据)不会泄露关于password的任何信息

      目的是对抗服务器妥协时泄露口令信息和服务器内部模拟用户

    已有的方案

    1. “Password-based authentication” 基于密码的身份验证: 不能应对服务器妥协和弱密码猜测

    2. “FIDO”: 高熵密钥(私钥)由用户拥有(通过加密硬件和软件管理,不便携),服务器端只拥有用于验证的公钥(不会泄露用户信息)

    3. ZWY 框架下的single-key PBC

    ZWY single-key PBC

    “ZWY framework(skPBC)”: 安全等级近似于key-based方案,无需用户储存密钥信息;

    • 在注册时获取 cryptographically strong access credential,可以随意安置(via untrusted cloud providers or copied on low-security devices)
    • 在线不可伪造性(服务器未妥协的情况下)
    • 达不到强不可伪造性和离线不可伪造性
    • 服务器妥协失去所有安全性:无需恢复密钥即可模拟所有用户验证
    • 不需要Pw-Hiding

    服务器拥有一个全局MAC密钥,用户凭证本质是服务器对uid生成的MAC密钥副本,注册时使用用户的password对MAC密钥进行对称加密。认证时,用户解密凭证恢复MAC密钥并与消息绑定后发送给服务器。(敌手可以让不诚实的用户注册后获取MAC密钥,但是此方案不考虑”corrupt users”的存在)

    敌手不知服务器的高熵MAC密钥,则无法验证解密后的值是否有效,从而确保在线不可伪造性。

    skPBC Syntax

    包括五个算法 “KGen, 〈RegU, RegS〉, Sign, Vf”,两个阶段“a registration phase and an authentication phase” ,两个参与方Server / User.

    Server: 长期单一密钥“KGen(λ) → (ssk, spk)”用于注册和验证所有用户,“ssk”是服务器的长期单一密钥,“spk”是与之对应的公钥

    注册阶段:用户:RegU(spk,uid,pw) → ask ; 服务器: 使用ssk签出ask并储存uid

    验证阶段:用户拟发送消息m,“Sign(uid, ask, pw, m) → τ”,将token τ和消息m发送给服务器,服务器执行“Vf(ssk, uid, m, τ ) → 0/1”

    ZWY Framework的安全目标和威胁模型

    选择消息和选择验证请求攻击下存在不可伪造性(“Existential Unforgeability under Chosen Message and Chosen Verification Queries Attack (EUF-CMVA)” (Dayanikli 和 Lehmann, 2024, p. 151))

    1. 经典的不可伪造:A只知道用户pw,对ask和server ssk一无所知
    2. 达到在线不可伪造性,A知道用户ask
    Game of weak/strong UNF for A in skPBC(λ):

    现有用户列表uid_1~n,及其对应pw_1~n

    敌手A可选择用户访问预言机Sign \ Vf 获取ask_i对挑战消息m进行签名和执行验证,请求过的(i,m)和i会被记录(分别在QRevCred中)

    A获胜条件:A给出uid_j (j∈[1,n],j∉RevCred,即合法的、从未请求过的用户)、新鲜的消息m*和签名τ*,如果验证通过则A获胜

    strongUNF实验中为A额外提供服务器私钥ssk

    Weak/Strong Unforgeability定义为对所有PPT敌手获胜以上实验的概率≤negl(λ)

    skPBC达不到Strong(and Offline) Unforgeability

    一旦敌手A得知服务器的密钥ssk,就能用自己选择的口令重新注册任意诚实的用户U,以获得有效的用户凭证,并以U的名义创建令牌。在skPBC方案下,敌手赢得strongUNF的概率为1。

    mkPBC

    skPBC不可能具有强不可伪造性,故引入多密钥的PBC。关键的区别在于,服务器不再具有单个密钥来颁发用户凭证和验证其令牌。而是为每个注册用户生成一个特定于用户的验证密钥,并在验证用户的令牌时使用该特定于用户的密钥。

    Syntax

    “A multi-key PBC scheme mkPBC = (Setup, 〈RegU, RegS〉, Sign, Vf)”

    Setup(λ)->pp: 输出公共参数,作为其他算法的隐式输入

    〈RegU(uid, pw), RegS(uid)〉 → (ask; avk): 注册交互,用户输出凭证ask,服务器输出用户特定的验证密钥 avk

    Sign(uid,ask,pw,m)  → τ : 对消息m生成授权令牌

    Vf(uid, avk, m, τ ) → 0/1 : 验证有效性

    Game of xUNF for A in mkPBC(λ) where x∈{strong,online,offline}

    现有合法注册的用户uid,pw,ask,avk,敌手在特定条件下多轮访问特定预言机后,给出新的m*,τ*,若通过验证则敌手获胜

    条件如下:

    • x=strong: 给予敌手avk和pw, 可访问Sign预言机(O_Sign会记录挑战消息m)
    • x=online: 给予敌手ask, 可访问Sign和Vf预言机
    • x=offline: 给予敌手ask, avk, 可访问Sign和TestPW预言机((pw’)=>pw==pw’)
    Game of PW-Hiding for A in mkPBC(λ)

    现有合法用户uid,均匀随机选取两个可能合法的pw: pw0和pw1,给予敌手avk(敌手此时只知道pw0和pw1,不知道具体选取的是哪一个)并访问Sign预言机(预言机知道选取的pw),之后敌手输出选取的是哪一个pw,正确则敌手获胜。

    mkPBC的安全定义

    对于一个mkPBC方案和所有PPT敌手A:

    • “Strong Unforgeability” :Pr[Game of strongUNF for A in mkPBC(λ)=1]≤negl(λ)
    • “Online Unforgeability” :Pr[Game of onlineUNF for A in mkPBC(λ)=1]≤(q_Vf+1)/|Dpw|+negl(λ),q_Vf是猜测次数(即访问Vf预言机次数),|Dpw|是口令域长度
    • “Offline Unforgeability” :Pr[Game of offlineUNF for A in mkPBC(λ)=1]≤qf/|Dpw|+negl(λ),qf是请求TestPW预言机次数
    • “Pw-Hiding” :Pr[Game of PW-Hiding for A in mkPBC(λ)=1]≤1/2+negl(λ)
    构建Sign-Then-Encrypt的PBC方案

    需要三个密码学原语:

    • 一个安全的伪随机函数PRF “F : {0, 1}^λ × X → Y”

      “安全的”意味着函数F(key, · )与同域的随机函数不可区分

    • 一个达到IND-CCA安全的非对称加密算法 ΠEnc:=(KGenE,Enc,Dec)

    • 一个达到EUF-CMA安全的签名算法:ΠSign:=(SetupS,KGenS,SignS,VfS)

      要求实现“Complete Robustness”(CROB-Security):即对于所有PPT敌手难以找到一对(消息,签名)能在两个不同的公钥下验证通过;

      以及“Randomness Injectivity” (RI)(可注入的随机性?可控的随机性?): 所有PPT敌手难以找到对于两个不同的注入参数,使得KGen输出相同的公私钥;暗含:公钥和私钥唯一匹配,对于注入参数而言是确定性生成的。

    Scheme

    一个基于签名后加密的多密钥PBC方案:

    • Setup(λ): pp ←SetupS(λ)

    • User与Server注册阶段 RegU(uid,pw) 和 RegS(uid):

      U: 均匀随机选取PRF密钥k←{0,1}^λ,运行KGenS(pp,F(k,pw))生成签名公私钥pkSig和skSig;

      运行KGenE(λ)生成加密用的公私钥pkEnc和skEnc;

      发送(uid,avk:=(pkSig,skEnc))到S,输出ask:=(k,pkEnc);

      签名和非对称加密的公私钥对都在客户端生成,发送签名公钥和加密私钥作为avk,保留PRF密钥k和加密公钥作为ask

      S: 接收(uid,avk)储存即可,RegS输出avk

    • Sign(uid,ask,pw,m)

      运行σ←SignS(skSig,(uid,m)) 对消息和uid签名

      运行τ←Enc(pkEnc,σ)

      输出τ作为token

    • Vf(uid,avk,m,τ)

      解密σ←Dec(skEnc,τ),输出VfS(pkSig,(uid,m),σ)

    Theorem & Proof 1.如果F是安全的PRF并且ΠSign是EUF-CMA安全的签名方案,则该PBC是强不可伪造的

    在服务器妥协(泄露avk)、用户pw泄露但是敌手不知道ask的情况下:敌手持有pkSig和skEnc,可解出令牌τ并得知其对应的(uid,m);未知ask则无法运行F(k,pw),就无法获得skSig。则可将问题归因到在未知skSig的情况下伪造签名,由于ΠSign是EUF-CMA安全,则不可行。即证明该PBC是强不可伪造的。

    2. 如果F是随机预言机,ΠSign具有complete robustness和randomness injectivity,且ΠEnc具有CCA安全,则该PBC是在线不可伪造的

    敌手具备 ask:=(k,pkEnc) 和 uid,未知avk:=(pkSign,skEnc)和pw。敌手通过猜测pw生成伪造的(pkSig’,skSig’):=KGenS(pp,F(k,pw’))和伪造签名σ’;由于ΠEnc具有CCA安全,则访问Sign预言机不会泄露任何关于签名σ的信息;由于未知pkSign则无法自行验证生成的签名,唯一的方法是访问Vf预言机。CROB确保Vf只会泄露pkSig的相等性,可注入随机性确保pkSig‘只能映射到单一pw猜测上,则敌手只能与Vf预言机一次猜测一次交互。至此该PBC是在线不可伪造的。

    3.  如果F是随机预言机,ΠSign是EUF-CMA安全的,并且具有可注入随机性,则该PBC是离线不可伪造的

    敌手具备ask,avk,uid,未知pw(作者在这里强调“具备ask”是指具备PRF密钥k,而不是签名私钥。注意到文中提及ask不储存而是即用即生成)。要伪造token τ则需要伪造skSig;此时敌手要么选择直接伪造签名(绕过skSig,但是ΠSign具有EUF-CMA安全则不可行),要么通过离线暴力破解pw以生成skSig。且由于F是随机预言机、ΠSign有可注入随机性则只有唯一的pw能计算出正确的skSig。此时敌手的每一次猜测必须访问一次随机预言机F,则该PBC是离线不可伪造的。

    4. 如果F是安全的PRF,则该PBC具有口令隐藏性

    方案中唯一依赖pw的是生成签名公私钥之时敌手知道pkSig但未知k,获取的方式是与Sign预言机交互。由于k是随即均匀选取的,且通过安全的PRF转换,则无法区分pkSig是由r=F(k,pw_b)还是从随机预言机中选取(此时avk独立于pw存在)。

    Appendix

    “The DSA, Schnorr and BLS signature scheme all achieve randomness injectivity information-theoretically. DSA and Schnorr are CROBsecure assuming a collision-resistant hash function, and BLS is informationtheoretically CROB-secure.” (Dayanikli 和 Lehmann, 2024, p. 165) DSA、Schnorr 和 BLS 签名方案在理论上都实现了随机性注入性信息。DSA 和 Schnorr 是假设具有抗碰撞哈希函数的 CROB安全,而 BLS 在信息理论上是 CROB 安全的。

    一些疑问
    1. 用户需要携带两个密钥(一个自己的password和一个PRF密钥k)牺牲了便携性。在具体的方案中,PRF应该使用流密码(e.g. AES)、HMAC或其他基于椭圆曲线构造的方案。其中某些方案并不支持所有k的长度,意味着要么选择HMAC这样支持所有长度的方案,然后让用户记住2个密钥,要么使用其他方案,k交由密钥管理器或安全芯片保管(没有FIDO的便捷性强,但是对保管方的安全性要求不高)。

      “We therefore do not store (or even generate) the key normally, but derive it deterministically as (pkSig, skSig) := KGenS(pp; F (k, pw)) from a PRF key k and the user’s password pw. The user now only stores the PRF key k and re-derives the signature key pair when she wants to generate an authentication token.” (Dayanikli 和 Lehmann, 2024, p. 158)

    2. 设想一个简单的“用户名+密码(口令)”授权登录的方式:服务器储存用户id和对应的口令加盐哈希,用户端请求注册和登录时提交口令明文的哈希(避免明文网络传输),在服务器内部对比后生成授权:

      • 不满足强不可伪造和离线不可伪造,服务器妥协时(泄露用户信息表,加盐算作服务器私钥的一部分)无需口令即可通过验证
      • 在线不可伪造:仅能通过访问服务器暴力破解
      • Pw-Hiding: 虽然满足,但是不能阻止服务器内部模拟用户

      如果再加一个口令是否会更安全?不会,只会更麻烦

      那么mkPBC的方案我认为优势就在于以下几点:

      • 避免服务器内部腐败,擅自模拟用户操作
      • 强不可伪造和离线不可伪造:服务器妥协和其中一个密钥(k;pw)泄露都无法获取授权
      • password可以是便于用户记住的口令,k可以像FIDO方案一样储存,但是对储存方式安全性要求较低

    友链

    :::note[题记] 那些在MIDI库里徘徊的十六分音符
    终究没能拼成告白的主歌

    我把周杰伦的《晴天》写成C++的类
    在每个midiEvent里埋藏故事的小黄花

    调试器的断点比初恋更漫长
    而青春不过是一串未导出的cmake工程文件

    在堆栈溢出的夜晚
    终将明白
    有些旋律永远停在#pragma once的注释里
    有些人永远停在未定义的引用里

    或许你我的心跳终归运行在不同的时钟频率
    却愿始终记得如何编译出一场永不落幕的晴天
    :::

    ::github{repo="TwilightLemon/SunnyDays"}
    就像在题记里说的一样,这是一个从未导出成功的工程文件。
    所以如果你也想听听,可以在PowerShell里运行以下指令:

    git clone https://github.com/TwilightLemon/SunnyDays
    cd SunnyDays
    mkdir build
    cd build
    cmake .. -G "MinGW Makefiles"
    mingw32-make
    ./SunnyDays.exe
    

    没环境?巧了,她也如是说。

    下面来简单讲讲如何使用C++和MIDI库作曲吧。

    一、开始工作 引入MIDI库和相关控制类
    • CMakeLists.txt中:
      target_link_libraries(SunnyDays winmm)
      
    • MIDIHelper.h中:
      #include <windows.h>
      #pragma comment(lib,"winmm.lib")
      
    • 定义Scale(音阶), Instrument(乐器, 仅包括部分)等枚举。我把Drum单独提了出来。
      enum Scale
      {
          X1 = 36, X2 = 38, X3 = 40, X4 = 41, X5 = 43, X6 = 45, X7 = 47,
          L1 = 48, L2 = 50, L3 = 52, L4 = 53, L5 = 55, L6 = 57, L7 = 59,
          M1 = 60, M2 = 62, M3 = 64, M4 = 65, M5 = 67, M6 = 69, M7 = 71,
          H1 = 72, H2 = 74, H3 = 76, H4 = 77, H5 = 79, H6 = 81, H7 = 83,
          LOW_SPEED = 500, MIDDLE_SPEED = 400, HIGH_SPEED = 300,
          _ = 0XFF
      };
      enum Drum{
          BassDrum = 36, SnareDrum = 38, ClosedHiHat = 42, OpenHiHat = 46
      };
      enum Instrument{
          AcousticGrandPiano = 0, BrightAcousticPiano = 1,
          ElectricGrandPiano = 2, HonkyTonkPiano = 3,
          ElectricPiano1 = 4, ElectricPiano2 = 5
      };
      
    • 一些基础方法,包括初始化/关闭设备、设置参数、播放单个音符和播放和弦等。
      void initDevice();
      void closeDevice();
      void setInstrument(int channel, int instrument);
      void setVolume(int channel, int volume);
      
      void PlayNote(HMIDIOUT handle, UINT channel, UINT note, UINT velocity);
      
      void playChord(HMIDIOUT handle, UINT channel, UINT note1, UINT note2, UINT note3, UINT note4, UINT velocity);
      
      void playChord(HMIDIOUT handle, UINT channel, UINT note1, UINT note2, UINT note3, UINT velocity);
      
      MIDIHelper.cpp中:
      void initDevice(){
          midiOutOpen(&hMidiOut, 0, 0, 0, CALLBACK_NULL);
      }
      
      void closeDevice(){
          midiOutClose(hMidiOut);
      }
      
      void setInstrument(int channel,int instrument){
          if (channel > 15 || instrument > 127) return;
          DWORD message = 0xC0 | channel | (instrument << 8);
          midiOutShortMsg(hMidiOut, message);
      }
      
      void setVolume(int channel,int volume){
          if (channel > 15 || volume > 127) return;
          DWORD message = 0xB0 | channel | (7 << 8) | (volume << 16);
          midiOutShortMsg(hMidiOut, message);
      }
      
      //播放单个音符,note是音符,velocity是力度
      void PlayNote(HMIDIOUT handle, UINT channel, UINT note, UINT velocity) {
          if (channel > 15 || note > 127 || velocity > 127) return;
          DWORD message = 0x90 | channel | (note << 8) | (velocity << 16);
          midiOutShortMsg(handle, message);
      }
      
      //四指和弦
      void playChord(HMIDIOUT handle, UINT channel, UINT note1, UINT note2, UINT note3, UINT note4, UINT velocity){
          if (channel > 15 || note1 > 127 || note2 > 127 || note3 > 127 || note4 > 127 || velocity > 127) return;
          DWORD message1 = 0x90 | channel | (note1 << 8) | (velocity << 16);
          DWORD message2 = 0x90 | channel | (note2 << 8) | (velocity << 16);
          DWORD message3 = 0x90 | channel | (note3 << 8) | (velocity << 16);
          DWORD message4 = 0x90 | channel | (note4 << 8) | (velocity << 16);
          midiOutShortMsg(handle, message1);
          midiOutShortMsg(handle, message2);
          midiOutShortMsg(handle, message3);
          midiOutShortMsg(handle, message4);
      }
      
      //三指和弦
      void playChord(HMIDIOUT handle, UINT channel, UINT note1, UINT note2, UINT note3, UINT velocity) {
          if (channel > 15 || note1 > 127 || note2 > 127 || note3 > 127 || velocity > 127) return;
          DWORD message1 = 0x90 | channel | (note1 << 8) | (velocity << 16);
          DWORD message2 = 0x90 | channel | (note2 << 8) | (velocity << 16);
          DWORD message3 = 0x90 | channel | (note3 << 8) | (velocity << 16);
          midiOutShortMsg(handle, message1);
          midiOutShortMsg(handle, message2);
          midiOutShortMsg(handle, message3);
      }
      
    初始化和结束

    先在头文件中定义一个全局MIDI句柄:

    extern HMIDIOUT hMidiOut;
    

    在入口处初始化MIDI设备并在结束时关闭:

    HMIDIOUT hMidiOut;
    int main() {
        initDevice();
        //...
        closeDevice();
        return 0;
    }
    

    初始化MIDI设备之后,为每一个乐器分配一个通道channel(0~15,通常9分配给打击类乐器,例如鼓组),控制音量volume,然后就可以开始演奏了。

    二、自制简易乐谱

    Voice.cpp为例,定义一个数组为频谱,控制停顿和音符,遍历数组播放:

    namespace SunnyDays{
        int channelVoice=1;
        void playVoice(int note, int velocity){
            PlayNote(hMidiOut, channelVoice, note, velocity);
        }
        void voice(){
            Sleep(13100);//等待前奏
            int sleep = 390;
            int data[] =
                    {
                        //故事的小黄花
                        -90,
                        300,M5,M5,M1,M1,_,M2,M3,_,
                        //从出生那年就飘着
                        -90,
                        M5,M5,M1,M1,0,M2,M3,300,M2,M1,_,
                        //童年的荡秋千
                        -90,
                        300,M5,M5,M1,M1,_,M2,M3,_,
                        //随记忆一直晃到现在
                        -90,  
                        M3,_,500,M2,M3,M4,M3,M2,M4,M3,700,M2,700,_,
                        //...
                    }
            for (auto i : data) {
                if(i==-30){logTime("Enter chorus");continue;}//调试用
                if(i==-90){NextLyric(); continue;}
                if (i == 0) { sleep = 180; continue; }
                //...
                if (i == _) {
                    Sleep(390);
                    continue;
                }
    
                playVoice(i, 80);
                Sleep(sleep);
            }
        }
    }
    

    打个鼓:

    namespace SunnyDays{
        int channelBassDrum=9;
    
        void playDrum(int note, int velocity, int duration){
            PlayNote(hMidiOut, channelBassDrum, note, velocity);
            if(duration>0) {
                Sleep(duration);
                PlayNote(hMidiOut, channelBassDrum, note, 0);
            }
        }
    
        void bassDrum(){
            Sleep(11260);
            cout<<"Drum Bass Start!"<<endl;
            playDrum(SnareDrum,100,180);
            playDrum(SnareDrum,100,210);
            playDrum(BassDrum, 100, 210);
            playDrum(SnareDrum,100,190);
            playDrum(BassDrum, 100, 210);
            playDrum(SnareDrum,100,200);
            playDrum(SnareDrum,100,200);
            playDrum(OpenHiHat,100,-1);
            Sleep(200);
            //...
        }
    }
    

    简易副歌和弦,是从B站一位up主那里学的(已经忘记是哪位了qwq):

    namespace SunnyDays {
        int channelChord=2;
        void chordLevel(int level,int sleep,int repeat=2,int vel=70){
            repeat--;
            int down=8;
            if(level==1){
                //一级和弦 加右指
                playChord(hMidiOut, channelChord, M1, M3, M5, L1, vel);
                while(repeat--) {
                    Sleep(sleep);
                    playChord(hMidiOut, channelChord, M1, M3, M5, vel - down);
                }
            }else if(level==3){
                //三级和弦 加右指
                playChord(hMidiOut, channelChord, M3, M5, M7, L3, vel);
                while(repeat--) {
                    Sleep(sleep);
                    playChord(hMidiOut, channelChord, M3, M5, M7, vel - down);
                }
            }
            //...
        }
        void chord(){
            Sleep(63724);
            int sleep=740;
            int data[]={
                    //刮风这天 我试过握着你手
                    1,4,
                    6,4,
                    //但偏偏 雨渐渐
                    4,2,
                    5,2,
                    //大到我看你不见
                    1,4,
                    //还有多久 我才能
                    3,4,
                    //↑ 在你身边
                    6,4,
                    //↓ 等到放晴的那天
                    4,4,
                    //↑ 也许我会比较好一点
                    5,4,
                    //..
            }
            int count=sizeof(data)/sizeof(int);
            for(int i=0;i<count;i+=2){
                cout<<"chord "<<data[i]<<"  x"<<data[i+1]<<endl;
                chordLevel(data[i],sleep,data[i+1]);
                Sleep(sleep);
            }
            //...
        }
    }
    
    三、合成演奏

    我用了一个笨蛋方法,用多线程单独控制每一个通道,然后在主线程中调用:

    int main(){
        //...
        initDevice();
        //设置音量
        setVolume(channelChord,80);
        setVolume(channelMainLine,80);
        setVolume(channelVoice,120);
        setVolume(channelBassDrum,80);
    
        //设置乐器(特定音色)
        setInstrument(channelChord,ElectricPiano1);
        setInstrument(channelMainLine,ElectricPiano1);
    
    
        system("pause");//按下回车,就开始啦
        beginLogger();
    
    
        thread t0(voice);
        thread t1(mainLine);
        thread t2(bassDrum);
        thread t3(chord);
        t0.join();
        t1.join();
        t2.join();
        t3.join();
    
        closeDevice();
        //...
    }
    

    (最后叠个甲,俺不懂音乐制作,更不会什么C++😿)

    友链

    <p style="text-indent: 2em;"> 最近在Crypto 2023上看到一篇有趣的文章<sup>[1]</sup>,其旨在一个存在拥有所有密钥并知道所有消息的“独裁者”的信道中,通过安排与常规密文无法区分的隐藏的“变形”消息来进行机密通信的方法——变形签名,但由于本人技术水平有限无法完整实现整个系统。而当阅读到其中的一个技术分支——Chaffing and Winnowing时惊喜地发现其实现方法之巧妙,又恰好在图灵班的密码学课程中学到了相关的Diffie-Hellman密钥交换协议和消息验证码MAC等知识,于是选取这篇上世纪的论文<sup>[2]</sup>来进行评论和仿真实验。 </p>

    <p style="text-indent: 2em;"> (是的你没看错,这是我在学校写的某低水平评论论文,觉得方法比较新颖巧妙,于是分享出来) </p>

    <p align="center"> 摘要: 本文介绍了 Rivest 提出的 Chaffing and Winnowing 技术,该技术通过在消息中混入无关信息 (chaff) 并添加认证码 (MAC) 来实现机密性,即使在拥有所有加密密钥的“独裁者”信道中进行通信也能保证消息安全。文章详细阐述了该技术的原理、应用场景、潜在威胁以及未来研究方向,并通过实验仿真实现了整个技术流程。 </p>

    一、简介

    <p style="text-indent: 2em;"> Rivest为我们介绍了一种新技术Chaffing and Winnowing——原意是指从谷粒中分离谷壳的过程,它不进行传统意义上的加密,而是将消息(wheat)分块并作认证,混入无关信息(chaff)之后再进行通信。 </p> <p style="text-indent: 2em;"> 该项技术可以说是变形签名<sup>[1]</sup>的奠基之作,二者同样考虑一个问题:若独裁者拥有一个“后门”能够恢复密钥来对消息进行解密,那么如何在这样的信道上为消息提供机密性。Rivest说“像往常一样,关于规范技术的政策辩论最终会被技术创新所淘汰。试图通过规范加密来规范保密性,关闭了一扇门,却留下了另外两扇门(隐写术和Chaffing and Winnowing).”后者与前者不同,隐写术<sup>[3]</sup>注重于在较大的、看似普通的信息(如图片)中隐藏机密,使得在算法不公开的前提下,一个PPT敌手无法有效区分机密内容和普通内容。显然这样的机密性是由算法保密性提供,并不符合卡尔霍夫原则<sup>[4]</sup>,即“一个密码系统的安全性不应依赖于算法的秘密性,而应依赖于密钥的秘密性”。 </p> <p style="text-indent: 2em;">   而在Chaffing and Winnowing中,消息机密性的保证被归因到MAC算法的认证性上,即在适应性选择明文攻击下具有存在不可伪造性<sup>[5]</sup>。对手无法怀疑两种数据包的存在,不具有机密认证则亦无法区分它们,即使原消息不受任何加密。 </p>

    二、技术概要

    <p style="text-indent: 2em;"> 原文中,作者循序渐进地介绍了这种技术的原理。 </p> <p style="text-indent: 2em;"> 总体而言,发送方与接收方共享一个密钥,发送消息有两个部分:认证(添加消息认证码MAC)和添加chaff;接收方会通过验证MAC去除chaff(这个过程称为“winnowing”)以获得原始消息。整个过程中,没有对任何东西进行加密,因此可能不受出口管制(MAC不是加密)。 </p> <p style="text-indent: 2em;"> 这是一个十分原始的想法,而后作者在考虑了实际运用的问题并做出诸多改进措施。 </p>

    • 消息包的拆分与组装中,定义一个消息包为包含序列号、消息和MAC的三元组,以便接收方除重、组装和识别丢失。并在这里提出一种优化:发送方按顺序发送包,接收方一旦验证成功该序列号,则丢弃后续所有相同序列号的包。
    • 一个良好的混淆过程会为消息使用的每一个序列号至少添加一个chaff。
    • 对手可能通过每个包裹的内容来区分chaff和wheat,无限拆分wheat只会让传输更加低效。 <p style="text-indent: 2em;"> 为了解决以上问题,作者引用了自己的一项技术——全或无加密和包变换<sup>[11]</sup>。简单来说,通过这种变换之后,只有接收者收到全部消息才可逆转变换得到原文,否则只能得到垃圾消息。(让我们把算法具体实现放在仿真实验的部分。)使用此变换后,再对消息进行分包签名和发送,能够减少敌手直接通过辨识消息来查找wheat组合的机会。 </p>
    三、研究分类、现状、难点分析与未来方向

    <p style="text-indent: 2em;"> 我们现在已经了解到Chaffing and Winnowing技术的原理,可以发现数据包被分为了两种——为己用和混淆视听。前者的用法似乎已经固定,后者则隐藏着更大的利用潜能与危机。 </p>

    1. 可否认加密<sup>[6]</sup>

    <p style="text-indent: 2em;"> 如果对于每个wheat消息包,都生成一个使用特定密钥MAC认证的chaff,该chaff实际包含无害的消息,当使用该特定密钥进行认证时只能得到无害的消息,而真正在通讯双方交流的内容则被视为垃圾。如此使得在没有正确的解密密钥的情况下无法证明明文消息的来源或存在,即可否认加密。缺点在于,如果暴力机关要求通讯者提供所有密钥,则始终无法证明其是否已经提供全部密钥。 </p>

    2. 防止流量分析

    <p style="text-indent: 2em;"> 我尚未查找到已有的研究,只有维基百科中提及该技术的变体能够在分组网络中防止消息泄露和流量分析<sup>[7]</sup>。 </p>

    3. 潜在的诬陷攻击

    <p style="text-indent: 2em;"> 试想通讯双方之间存在一个发起中间人攻击的主动敌手,能够用自己的密钥生成MAC并嵌入有害信息,这对于通讯双方接受消息没有影响。此时敌手拥有通讯的全文和自己的密钥,则他可以对通信双方进行诬陷:指定其通讯内容为有害信息而他们无法辩解。一方面,由于可否认加密的存在,他们可被认定为提供虚假无害的消息密钥;另一方面,通讯双方根本没有机密性需求,也没有使用Chaffing and Winnowing技术,他们本身就没有密钥,敌手嵌入的信息在通讯双方的可忽视区内。 </p>

    4. 如何协商一个私钥

    <p style="text-indent: 2em;"> 原文中仅用一个段落草草带过双方协商密钥的过程——“例如”使用Diffie-Hellman密钥交换协议<sup>[8]</sup>,即通讯双方交换对方的公钥与自己的私钥计算得到共有的密钥。然而原始的协议仅在窃听敌手存在的情况下是安全的,通讯双方并不知道对方的身份,如果要抵御主动攻击敌手,则需要涉及数字证书和指定验证者签名<sup>[9]</sup>等技术。这不在作者Rivest讨论的范围内,因为他的安全目标规定独裁者只知道加密密钥,而不限制认证。 </p>

    5. 消息体积剧增与对抗暴力枚举

    <p style="text-indent: 2em;"> 通讯双方仍需发送足够量的chaff包以迷惑敌手,使之在计算上找到包的组合不可行。这也无疑增大了包的体积,加之需要足够长度的MAC对抗碰撞。 </p>

    目前该技术亟需解决的问题个人认为就是以上的3、4、5点;由此技术衍生的变形加密和变形签名相关研究已连续两年在CRYPTO发表<sup>[1][10]</sup>。

    四、实验仿真

    以下使用C# .NET 9 on Windows平台进行实验,模拟通讯双方使用Chaffing and Winnowing技术的全部过程。

    1. 通讯双方协商密钥

    生成ECDiffieHellmanCng实体并生成密钥对,输出公钥,要求输入私钥后计算共同密钥:

    Console.WriteLine("Step 1: Key Exchange");
    Console.WriteLine("Generating key...");
    using var client = new ECDiffieHellmanCng()
    {
        KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
        HashAlgorithm = CngAlgorithm.Sha256
    };
    var publicKey = client.PublicKey.ToByteArray();
    Console.WriteLine($"Public Key: {Convert.ToBase64String(publicKey)}");
    Console.WriteLine("Enter the public key of the other party:");
    string otherKey = Console.ReadLine();
    byte[] otherPublicKey = Convert.FromBase64String(otherKey);
    var privateKey = client.DeriveKeyMaterial(CngKey.Import(otherPublicKey, CngKeyBlobFormat.EccPublicBlob));
    
    2. 实现一个AONT变换

    这里采用原作者的简单变换:将数据按BLOCK_SIZE分块,生成与块等大的随机生成的密钥块key,将每个数据块与key逐比特异或得到结果,再将key与结果做异或储存在结果的最后一块之后:

    public static readonly int BLOCK_SIZE = 16;
        public static byte[] Transform(byte[] data){
            int blocks= (data.Length+BLOCK_SIZE-1)/BLOCK_SIZE;
            byte[] result = new byte[(blocks+1)*BLOCK_SIZE];//reserve one block for the hash
            byte[] key= new byte[BLOCK_SIZE];
            RandomNumberGenerator.Fill(key);
    
            Console.WriteLine($"Key: {string.Join(',',key)}");
    
            for(int i=0;i<blocks;i++){
                int offset = i*BLOCK_SIZE;
                for(int j=0;j<BLOCK_SIZE&&offset+j<data.Length;j++){
                    result[offset+j]=(byte)(data[offset+j]^key[j]);
                }
            }
    
            for(int i=0;i<blocks*BLOCK_SIZE;i++){
                key[i%BLOCK_SIZE]^=result[i];  //key XOR with data blocks
            }
            Array.Copy(key,0,result,blocks*BLOCK_SIZE,BLOCK_SIZE);
            
            Console.WriteLine($"Last Block: {string.Join(',',key)}");
    
            return result;
        }
    

    逆变换即先按BLOCK_SIZE分块,取出最后一块,依次与数据块做异或,解出key,再用key与数据块做异或还原原始数据。(注意,后续分包时,包的大小应该为BLOCK_SIZE的整数倍,以确保key按照相同的方式还原;逆变换时可能发现最后一块为{0}*,这并不影响解除key,因为与0异或为其本身。)

    public static bool Reverse(byte[] data,out byte[] result){
        if(data.Length%BLOCK_SIZE!=0){
            result=null;
            return false;
        }
    
        int oriBlocks = data.Length/BLOCK_SIZE-1;
        result= new byte[oriBlocks*BLOCK_SIZE];
    
        byte[] key= new byte[BLOCK_SIZE];
        Array.Copy(data,oriBlocks*BLOCK_SIZE,key,0,BLOCK_SIZE);
        Console.WriteLine($"Last Block: {string.Join(',',key)}");
            
        for(int i=0;i<oriBlocks*BLOCK_SIZE;i++){
            key[i%BLOCK_SIZE]^=data[i];  //key XOR with data blocks
        }
        Console.WriteLine($"Key: {string.Join(',',key)}");
    
        for(int i=0;i<oriBlocks;i++){
            int offset = i*BLOCK_SIZE;
            for(int j=0;j<BLOCK_SIZE&&offset+j<result.Length;j++){
                result[offset+j]=(byte)(data[offset+j]^key[j]);
            }
        }
    
        return true;
    }
    

    以上,如果不首先访问消息的每个块,就不可能恢复原始明文。

    有后人使用更复杂的算法实现AONT,例如使用线性变换而无任何加密假设的Stinson 算法<sup>[12]</sup>。似乎能提供更高的安全性。

    调用ANOT变换,这里预先设定了发送的消息。

    Console.WriteLine("Step 2: AONT");
    string content = """
        The power to authenticate is in many cases the power to control, 
        and handing all authentication power to the government is beyond all reason. 
                                                        -- Ronald L. Rivest, 1998
        """;
    byte[] dataBytes = Encoding.UTF8.GetBytes(content);
    byte[] transformed = AONT.Transform(dataBytes);
    
    3. 创建MAC消息验证码

    这里使用HMAC-SHA256算法<sup>[13][14]</sup>给出简单的MAC算法三元组,其中Gen已由最初的密钥交换提供。

        public static byte[] Sign(byte[] key,byte[] data){
            using var hmac = new HMACSHA256(key);
            return hmac.ComputeHash(data);
        }
        public static bool Verify(byte[] key,byte[] data,byte[] signature){
            using var hmac = new HMACSHA256(key);
            byte[] computed = hmac.ComputeHash(data);
            return computed.Length==signature.Length&&computed.AsSpan().SequenceEqual(signature);
        }
    
    4. 分包和签名
    Console.WriteLine("Step 3: Packaging and Signing");
    int numBlocks = (transformed.Length + BLOCK_SIZE - 1) / BLOCK_SIZE;
    List<Package> packages = [];
    for (int index = 0; index < numBlocks; index++)
    {
        int offset = index * BLOCK_SIZE;
        int blockSize = Math.Min(BLOCK_SIZE, transformed.Length - offset);
        byte[] block = new byte[BLOCK_SIZE];
        Array.Copy(transformed, offset, block, 0, blockSize);
    
        byte[] signature = HMACHelper.Sign(privateKey, block);
        packages.Add(new Package(index, block, signature));
    }
    int packageCount = packages.Count;
    Console.WriteLine($"Wheat packages: {packageCount}");
    
    5. 加入带有随机数据的chaff
    Console.WriteLine("Step 4: Adding Chaff Packages");
    var rand = new Random();
    for (int i = 0; i < packageCount; i++)
    {
        int randCount = rand.Next(1, 5);
        for (int j = 0; j < randCount; j++)
        {
            var randData = new byte[BLOCK_SIZE];
            RandomNumberGenerator.Fill(randData);
            var randSignature = new byte[32];
            RandomNumberGenerator.Fill(randSignature);
            packages.Add(new Package(i, randData, randSignature));
        }
    }
    var sendPkg = packages.OrderBy(p => p.index);
    
    6. 模拟发送

    将所有的包按照index顺序排列后以Base64编码输出模拟发送,在接收端输入内容模拟接收。Base64编码能将byte[]转为文本格式,便于实验。

    Console.WriteLine("Step 5: Sending Packages");
    foreach (var pkg in sendPkg)
    {
        Console.WriteLine($"{pkg.index},{Convert.ToBase64String(pkg.data)},{Convert.ToBase64String(pkg.signature)}");
    }
    Console.ReadLine();
    
    7. 模拟接收

    要求输入所有的包,键空以结束。

    Console.WriteLine("Enter packages, done with empty line:");
    List<Package> received = [];
    try
    {
          while (true)
          {
               string line = Console.ReadLine();
                if (string.IsNullOrEmpty(line)) break;
                string[] parts = line.Split(',');
                int index = int.Parse(parts[0]);
                byte[] data = Convert.FromBase64String(parts[1]);
                byte[] signature = Convert.FromBase64String(parts[2]);
                received.Add(new Package(index, data, signature));
          }
            Console.WriteLine($"Received packages: {received.Count}");
    }
    catch
    {
         Console.WriteLine("Invalid input.");
         continue;
    }
    
    8. Winnowing和逆变获得原消息
    Console.WriteLine("Winnowing...");
            var wheat = received.Where(p => HMACHelper.Verify(privateKey, p.data, p.signature)).OrderBy(p => p.index).ToList();
            var wheatCount = wheat.Count;
            Console.WriteLine($"Wheat packages: {wheatCount}");
    
            Console.WriteLine("Reverse AONT...");
            byte[] assembly = new byte[wheatCount * BLOCK_SIZE];
            for (int i = 0; i < wheatCount; i++)
            {
                Array.Copy(wheat[i].data, 0, assembly, i * BLOCK_SIZE, BLOCK_SIZE);
            }
            Console.WriteLine($"Assembly: {Convert.ToBase64String(assembly)}");
            if (AONT.Reverse(assembly, out byte[] result))
            {
                Console.WriteLine($"Result: {Encoding.UTF8.GetString(result)}");
            }
            else
            {
                Console.WriteLine("Reverse failed.");
            }
    
    9. 测试

    两实例交换公钥并在内部生成私钥:

    发送方生成消息包:

    接收方收到不完整包流,逆变得到乱码;如果接受不完整块流,逆变将失败:

    只有完整获得包流才能解出原始信息:

    :::note[注释]
    为了方便起见,这里没有处理原消息长度,padding产生的字节被编为乱码。
    在实际运用中,包的结构并非像实验中一样直接暴露。
    以上实验项目代码在Github上由本人公开。
    ::: ::github{repo="TwilightLemon/TestCWCrypto"}

    五、结论

    Chaffing and Winnowing 技术提供了一种非传统的思路,利用 MAC 的认证性为消息提供机密性保障,即使在拥有所有加密密钥的信道中也能保证消息安全。该技术具有潜在的应用价值,但仍需解决一些挑战,例如协商私钥的安全性和消息体积的膨胀。未来研究可以探索更复杂的混淆过程、更高效的压缩算法以及更安全的密钥协商协议,以进一步提升 Chaffing and Winnowing 技术的安全性、效率和实用性。

    参考文献

    [1] Kutyłowski, M., Persiano, G., Phan, D.H., Yung, M., Zawada, M. (2023). “Anamorphic Signatures: Secrecy from a Dictator Who Only Permits Authentication!”. In: Handschuh, H., Lysyanskaya, A. (eds) Advances in Cryptology – CRYPTO 2023. Lecture Notes in Computer Science, vol 14082. Springer, Cham. https://doi.org/10.1007/978-3-031-38545-2_25

    [2] Ronald L. Rivest. “Chaffing and Winnowing: Confidentiality without Encryption”. Cryptobytes, Summer 1998. MIT Laboratory for Computer Science. Web. 23 Nov. 2024. https://people.csail.mit.edu/rivest/pubs/Riv98a.pdf

    [3] Peter Wayner. 1996. “Disappearing cryptography: being and nothingness on the net”. Academic Press Professional, Inc., USA. https://dl.acm.org/doi/10.5555/229879

    [4] Kerckhoffs, A. (1883). “La cryptographie militaire”. Journal des sciences militaires. https://www.petitcolas.net/kerckhoffs/crypto_militaire_1.pdf

    [5] Krawczyk, H., Bellare, M., and R. Canetti, “HMAC: Keyed-Hashing for Message Authentication”, RFC2104, February 1997. https://www.rfc-editor.org/rfc/rfc2104

    [6] Canetti, Ran, Cynthia Dwork, Moni Naor, and Rafail Ostrovsky, “Deniable Encryption”, Proceedings CRYPTO ’97 (Springer 1997). https://link.springer.com/content/pdf/10.1007/BFb0052229.pdf

    [7] Chaffing and Winnowing – Variations WikiPedia. https://en.wikipedia.org/wiki/Chaffing_and_winnowing#Variations

    [8] Diffie, Whitfield; Hellman, Martin E. (November 1976). “New Directions in Cryptography”. IEEE Transactions on Information Theory. https://ee.stanford.edu/~hellman/publications/24.pdf

    [9] Jakobsson, Markus, Kazue Sako, and Russell Impagliazzo, “Designated Verifier Proofs and Their Applications’’, Pro-ceedings Eurocrypt ’ 96 (Springer 1996), 143—154. https://link.springer.com/content/pdf/10.1007/3-540-68339-9_13.pdf

    [10] Persiano, G., Phan, D.H., Yung, M. (2022). “Anamorphic Encryption: Private Communication Against a Dictator”. In: Dunkelman, O., Dziembowski, S. (eds) Advances in Cryptology – EUROCRYPT 2022. EUROCRYPT 2022. Lecture Notes in Computer Science, vol 13276. Springer, Cham. https://doi.org/10.1007/978-3-031-07085-3_2

    [11] Rivest, R. “All-Or-Nothing Encryption and the Package Transform”. Proceedings of the 1997 Fast Software Encryption Conference (Springer, 1997). https://people.csail.mit.edu/rivest/pubs/Riv97d.pdf

    [12] Stinson, D.R. “Something About All or Nothing (Transforms)”. Designs, Codes and Cryptography 22, 133–138 (2001). https://link.springer.com/article/10.1023/A:1008304703074

    [13] HMACSHA256 Class (System.Security.Cryptography) | Microsoft Learn. https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hmacsha256

    [14] Preneel, B. (2024). “HMAC”. In: Jajodia, S., Samarati, P., Yung, M. (eds) Encyclopedia of Cryptography, Security and Privacy. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-642-27739-9_581-2

    [15] Siriwardena, P. (2020). “Base64 URL Encoding”. In: Advanced API Security. Apress, Berkeley, CA. https://doi.org/10.1007/978-1-4842-2050-4_20