我从Active Directory检索一个objectsid
值。它是一个base64编码的字符串。
我有以下函数(如下)将其解码为实际的SID文本字符串。
下面的函数在除少数以外的所有情况下都能正常工作.在Active Directory属性编辑器中检查时,SID为"S-1-521 - 3477787073 - 812361429 - 3477787073,被返回为"S-1-421 - 3477787073 - 812361429 - 3477787073"。第三位数字差1
同样,SID为"S-1-532 - 573"返回为"S-1-2-32-573",第三位又少了3。
我已经调试了足够多,找出是byte[]数组的长度不同,我认为这是导致这个错误的原因。
当字节数组为28位时,解码正确。如果小于28位,则与byte[]数组的长度直接相关,第三个SID数字关闭。
我认为有一些关于for()循环条件i < bytes[7]
,即使byte[7]
似乎总是5
在所有情况下(至少那些我已经断点)。
或者可能是BitConverter的第二个参数(8 + (i * 4))
。如果byte[7]
总是5,那么(5*4)+ 8 = 28。当字节数组是28位时,返回值总是正确的。当byte[]数组小于28位时,返回值是错误的。
我没有写这个函数(在另一个堆栈溢出问题的答案中找到),所以我真的不明白它在做什么,除了我在这里描述的。我确实添加了代码注释。
public static string Base64DecodeSID(string data) {
if (data == "") {
return "";
}
byte[] bytes = Convert.FromBase64String(data);
try {
string sid = "S-" + bytes[0].ToString(); // Add SID revision.
if (bytes[6] != 0 || bytes[5] != 0) { // SID authority
sid += ("-" +
String.Format( // Left 0-pad hex
"0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}", // values to 2 places.
bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6]
)
);
} else {
sid += ("-" + (bytes[1] + (bytes[2] << 8) + (bytes[3] << 16) + (bytes[4] << 24)).ToString());
}
for (int i = 0; i < bytes[7]; i++) { // Sub-Authority...
sid += ("-" + BitConverter.ToUInt32(bytes, 8 + (i * 4)).ToString());
}
return sid;
}
(为了简洁,我省略了catch())
例子Base64:"AQQAAAAAAAUVAAAAwdFKz9WmazDFb3Y8"
已解码字节[]数组:
[00] 1
[01] 4
[02] 0
[03] 0
[04] 0
[05] 0
[06] 0
[07] 5
[08] 21
[09] 0
[10] 0
[11] 0
[12] 193
[13] 209
[14] 74
[15] 207
[16] 213
[17] 166
[18] 107
[19] 48
[20] 197
[21] 111
[22] 118
[23] 60
期望值:"S-1-521 - 3477787073 - 812361429 - 3477787073,
实际返回值:"S-1-421 - 3477787073 - 812361429 - 3477787073,你知道怎么解决这个问题吗?我是否需要将数组填充到28位,甚至32位?
正如评论中所指出的,SecurityIdentifier
类使这很容易:
public static string Base64DecodeSID(string data) {
var bytes = Convert.FromBase64String(data);
var sid = new SecurityIdentifier(bytes, 0);
return sid.Value;
}
你可能想在那里添加一些错误检查,以防它传递了一个坏值。
调用Base64DecodeSID("AQQAAAAAAAUVAAAAwdFKz9WmazDFb3Y8")
返回S-1-5-21-3477787073-812361429-1014394821