A security identifier (SID) is an unique identifier, commonly used in Microsoft’s systems. For example, it’s used to identify users within Windows, or, more generally, within an Active Directory.
The SID is a binary value, with a variable length, that can be also be represented as a string. This conversion is implemented by the function called ConvertSidToStringSid
, provided by the library Advapi32.dll
, available only in Windows.
Hence, if you need to perform this conversion, you can procede with one of these two paths:
- Use Advapi32 (only in Windows)
- Rewrite the conversion
A string SID has this format:
S-1-IdentifierAuthority-SubAuthority1-SubAuthority2-...-SubAuthoritynThis syntax is defined formally, using the ABNF in this way:
SID= "S-1-" IdentifierAuthority 1*SubAuthority IdentifierAuthority= IdentifierAuthorityDec / IdentifierAuthorityHex ; If the identifier authority is < 2^32, the ; identifier authority is represented as a decimal ; number ; If the identifier authority is >= 2^32, ; the identifier authority is represented in ; hexadecimal IdentifierAuthorityDec = 1*10DIGIT ; IdentifierAuthorityDec, top level authority of a ; security identifier is represented as a decimal number IdentifierAuthorityHex = "0x" 12HEXDIG ; IdentifierAuthorityHex, the top-level authority of a ; security identifier is represented as a hexadecimal number SubAuthority= "-" 1*10DIGIT ; Sub-Authority is always represented as a decimal number ; No leading "0" characters are allowed when IdentifierAuthority ; or SubAuthority is represented as a decimal number ; All hexadecimal digits must be output in string format, ; pre-pended by "0x"Each field corresponds to a particular group of bytes of the binary SID. This correspondence has also been defined formally. With these information, this is the final algorithm that I implemented in Java:
public static String convertSidToStringSid(byte[] sid) { int offset, size; // sid[0] is the Revision, we allow only version 1, because it's the // only that exists right now. if (sid[0] != 1) throw new IllegalArgumentException("SID revision must be 1"); StringBuilder stringSidBuilder = new StringBuilder("S-1-"); // The next byte specifies the numbers of sub authorities (number of // dashes minus two) int subAuthorityCount = sid[1] & 0xFF; // IdentifierAuthority (6 bytes starting from the second) (big endian) long identifierAuthority = 0; offset = 2; size = 6; for (int i = 0; i < size; i++) { identifierAuthority |= (long) (sid[offset + i] & 0xFF) << (8 * (size - 1 - i)); // The & 0xFF is necessary because byte is signed in Java } if (identifierAuthority < Math.pow(2, 32)) { stringSidBuilder.append(Long.toString(identifierAuthority)); } else { stringSidBuilder.append("0x").append( Long.toHexString(identifierAuthority).toUpperCase()); } // Iterate all the SubAuthority (little-endian) offset = 8; size = 4; // 32-bits (4 bytes) for each SubAuthority for (int i = 0; i < subAuthorityCount; i++, offset += size) { long subAuthority = 0; for (int j = 0; j < size; j++) { subAuthority |= (long) (sid[offset + j] & 0xFF) << (8 * j); // The & 0xFF is necessary because byte is signed in Java } stringSidBuilder.append("-").append(subAuthority); } return stringSidBuilder.toString(); }This algorithm has been tested generating a lot of SIDs combinations, and comparing the results with the ones returned by the original conversion in
Advapi32.dll
. Just to have an idea, the following code is a particular function used for the tests.
private static void generateCombinations(byte[] sid, int offset) throws Exception { String convertedSid, convertedSid2; if (offset >= sid.length) { convertedSid = Advapi32Util.convertSidToStringSid(new PSID(sid)); convertedSid2 = convertSidToStringSid(sid); if (!convertedSid.equals(convertedSid2)) { throw new Exception("Conversion Error: " + convertedSid2 + " instead of " + convertedSid); } return; } for (int i = 0; i <= 255; i += 255/3) { sid[offset] = (byte)(i & 0xFF); generateCombinations(sid, offset+1); } }
Complete project
Download the complete algorithm, with also the tests.
2 responses to “Convert a SID to String with Java”