1

c# donet 可以为以下 java 代码生成相同的 UUID 吗?如果是这样怎么办?我试过 GUID 但没有用!

文本:

String cleartext = "CN=CompanyName;mac=some mac;@host=somehost;email=admin@somedomain.com;issued=01/01/20013;expire=12/12/2013";

Java代码:

UUID uuid = UUID.nameUUIDFromBytes(cleartext.getBytes("UTF-8"));

C#代码:

byte[] b = System.Text.Encoding.UTF8.GetBytes(cleartext);
        Guid uid = new Guid(b);
        Console.Write(uid.ToString());

REF 早期讨论

4

3 回答 3

12

如果您只需要相同的 UUID 字符串(而不是实际的 UUID/Guid 对象),则此 C# 方法将返回与 Java 方法相同的值UUID.nameUUIDFromBytes(byte[])

public static string NameUUIDFromBytes(byte[] input)
{
    MD5 md5 = MD5.Create();
    byte[] hash = md5.ComputeHash(input);
    hash[6] &= 0x0f;
    hash[6] |= 0x30;
    hash[8] &= 0x3f;
    hash[8] |= 0x80;
    string hex = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower();
    return hex.Insert(8, "-").Insert(13, "-").Insert(18, "-").Insert(23, "-");
}

C# 示例

string test = "test";
Console.Out.WriteLine(NameUUIDFromBytes(Encoding.UTF8.GetBytes(test)));

Output:
098f6bcd-4621-3373-8ade-4e832627b4f6

Java 示例

UUID test = UUID.nameUUIDFromBytes("test".getBytes("UTF-8"));
System.out.println(test);

Output:
098f6bcd-4621-3373-8ade-4e832627b4f6

编辑:我知道这是事后的事,但这会产生一个Guid具有相同值的实际对象。以防万一有人想要。

public static Guid NameGuidFromBytes(byte[] input)
{
    MD5 md5 = MD5.Create();
    byte[] hash = md5.ComputeHash(input);
    hash[6] &= 0x0f;
    hash[6] |= 0x30;
    hash[8] &= 0x3f;
    hash[8] |= 0x80;

    byte temp = hash[6];
    hash[6] = hash[7];
    hash[7] = temp;

    temp = hash[4];
    hash[4] = hash[5];
    hash[5] = temp;

    temp = hash[0];
    hash[0] = hash[3];
    hash[3] = temp;

    temp = hash[1];
    hash[1] = hash[2];
    hash[2] = temp;
    return new Guid(hash);
}
于 2013-08-02T17:48:41.020 回答
1

此代码绝对不适用于 .NET。

构造Guid(Byte[])函数必须 占用 16 个字节(因为 Guid 是 128 位),否则将抛出 ArgumentException。您的字符串远远超过 16 个字节。

然而,话虽如此,C# 和 Java仍然不会使用传递给构造函数的相同 16 个字节生成相同的 UUID。在 Java 中,您可以将任意数量的字节传递给UUID构造函数,它将创建这些字节的散列。换句话说:

在 C# 中:

Guid g = new Guid(new Byte[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16});
Console.WriteLine(g);

将产生与以下不同的值:

UUID u = UUID.nameUUIDFromBytes(new byte[] {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16});
System.out.println(u);

...在Java中。

您可能可以Byte[16]在 Java 中实现 .NET 的构造函数,或者在 .NET 中实现 Java 的哈希构造函数,但我建议在两个平台上使用 UUID 的字符串表示形式,例如"190c4c10-5786-3212-9d85-018939108a6c".

如果您尝试从字符串创建散列,您可能需要检查 MD5 类。你会想要这样的东西:

var md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(cleartext);
byte[] hashBytes  = md5.ComputeHash(inputBytes);

MD5 是一种标准算法,将在 .NET 和 Java 中为相同的字符串生成相同的哈希值。

于 2013-08-02T16:35:27.863 回答
0

如果您想要互操作性,请不要依赖不受您控制的代码。它可能会随着每个 Java 版本或实现而改变。

你可以采取使用的方式

/**
 * Static factory to retrieve a type 3 (name based) {@code UUID} based on
 * the specified byte array.
 *
 * @param  name
 *         A byte array to be used to construct a {@code UUID}
 *
 * @return  A {@code UUID} generated from the specified array
 */
public static UUID nameUUIDFromBytes(byte[] name) {
    MessageDigest md;
    try {
        md = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException nsae) {
        throw new InternalError("MD5 not supported");
    }
    byte[] md5Bytes = md.digest(name);
    md5Bytes[6]  &= 0x0f;  /* clear version        */
    md5Bytes[6]  |= 0x30;  /* set to version 3     */
    md5Bytes[8]  &= 0x3f;  /* clear variant        */
    md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(md5Bytes);
}

来源

并将其复制到您的代码中。也可以用其他语言准确地创建它,您的问题应该消失了。

如果“类型 3(基于名称)UUID”是精确指定结果的标准,您可以跳过在 Java 中复制它,因为实现永远不应该返回不同的结果。您可能还会找到其他语言的实现,并且不需要手动移植它。

于 2013-08-02T16:46:06.043 回答