如何在VBA中执行密码存储的Unicode归一化?

发布于 2025-01-25 15:17:19 字数 233 浏览 3 评论 0原文

我想在VBA中存储和比较Hashed密码。

我已经阅读我如何正确地实现Unicode密码?,但是我不知道从哪里开始。

如何在VBA中标准化Unicode字符串?

最好是,我会在不下载ICU的情况下执行此操作。链接的帖子是指的,因为我希望我的项目不依赖外部代码。

I want to store and compare hashed passwords in VBA.

I've read How do I properly implement Unicode passwords?, but I have no clue about where to start.

How do I normalize a unicode string in VBA?

Preferably, I'd do this without downloading the ICU the linked post refers to, because I'd like my project not to be dependent on external code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在夏天 2025-02-01 15:17:19

Windows提供了用于标准化字符串的内置 - unaryizestring函数。但是,使用可能有点棘手。

这是基于上面提供的文档中的C示例的实现:

'Declare the function
Public Declare PtrSafe Function NormalizeString Lib "Normaliz.dll" (ByVal NormForm As Byte, ByVal lpSrcString As LongPtr, ByVal cwSrcLength As Long, ByVal lpDstString As LongPtr, ByVal cwDstLength As Long) As Long
'And a relevant error code
Const ERROR_INSUFFICIENT_BUFFER = 122
'And a helper enum
Public Enum NORM_FORM
  NormalizationC = &H1
  NormalizationD = &H2
  NormalizationKC = &H5
  NormalizationKD = &H6
End Enum

'Available normalization forms can be found under https://learn.microsoft.com/en-us/windows/win32/api/winnls/ne-winnls-norm_form
'KD normalization is preferred(https://stackoverflow.com/a/16173329/7296893)  when hashing characters
'If you already have hashes stored, C normalization is least likely to break them
Public Function UnicodeNormalizeString(str As String, Optional norm_form As Byte = NormalizationKD) As String
    If Len(str) = 0 Then 'Zero-length strings can't be normalized
        UnicodeNormalizeString = str
        Exit Function
    End If
    Dim outlenestimate As Long
    'Get an initial length estimate for the string
    outlenestimate = NormalizeString(norm_form, StrPtr(str), Len(str), 0, 0)
    
    Dim i As Long
    'Try 10 times
    For i = 1 To 10
        'Initialize buffer
        UnicodeNormalizeString = String(outlenestimate, vbNullChar)
        'Get either the normalized string, or a new length estimate
        outlenestimate = NormalizeString(norm_form, StrPtr(str), Len(str), StrPtr(UnicodeNormalizeString), outlenestimate)
        If outlenestimate > 0 Then 'We got the normalized string
            'Truncate off the unused characters
            UnicodeNormalizeString = Left(UnicodeNormalizeString, outlenestimate)
            Exit Function
        Else
            If Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER Then
                Exit For 'An unexpected error occurred
            End If
            outlenestimate = outlenestimate * -1 'Use the new length estimate, try again
        End If
    Next
    Err.Raise 5000, Description:="Failure to normalize unicode string"
End Function

一旦您声明了标准化功能,请在哈希(Hashing)之前通过它运行密码:

If SomeHashFun(UnicodeNormalizeString(MyPassword)) = SomeHashedPassword Then
   'We are in!
End If

Windows provides a built-in for normalizing strings, the NormalizeString function. However, it can be a bit tricky to use.

Here is an implementation, based on the C example in the docs provided above:

'Declare the function
Public Declare PtrSafe Function NormalizeString Lib "Normaliz.dll" (ByVal NormForm As Byte, ByVal lpSrcString As LongPtr, ByVal cwSrcLength As Long, ByVal lpDstString As LongPtr, ByVal cwDstLength As Long) As Long
'And a relevant error code
Const ERROR_INSUFFICIENT_BUFFER = 122
'And a helper enum
Public Enum NORM_FORM
  NormalizationC = &H1
  NormalizationD = &H2
  NormalizationKC = &H5
  NormalizationKD = &H6
End Enum

'Available normalization forms can be found under https://learn.microsoft.com/en-us/windows/win32/api/winnls/ne-winnls-norm_form
'KD normalization is preferred(https://stackoverflow.com/a/16173329/7296893)  when hashing characters
'If you already have hashes stored, C normalization is least likely to break them
Public Function UnicodeNormalizeString(str As String, Optional norm_form As Byte = NormalizationKD) As String
    If Len(str) = 0 Then 'Zero-length strings can't be normalized
        UnicodeNormalizeString = str
        Exit Function
    End If
    Dim outlenestimate As Long
    'Get an initial length estimate for the string
    outlenestimate = NormalizeString(norm_form, StrPtr(str), Len(str), 0, 0)
    
    Dim i As Long
    'Try 10 times
    For i = 1 To 10
        'Initialize buffer
        UnicodeNormalizeString = String(outlenestimate, vbNullChar)
        'Get either the normalized string, or a new length estimate
        outlenestimate = NormalizeString(norm_form, StrPtr(str), Len(str), StrPtr(UnicodeNormalizeString), outlenestimate)
        If outlenestimate > 0 Then 'We got the normalized string
            'Truncate off the unused characters
            UnicodeNormalizeString = Left(UnicodeNormalizeString, outlenestimate)
            Exit Function
        Else
            If Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER Then
                Exit For 'An unexpected error occurred
            End If
            outlenestimate = outlenestimate * -1 'Use the new length estimate, try again
        End If
    Next
    Err.Raise 5000, Description:="Failure to normalize unicode string"
End Function

Once you have declared the normalization function, always run your password through it before hashing:

If SomeHashFun(UnicodeNormalizeString(MyPassword)) = SomeHashedPassword Then
   'We are in!
End If
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文