UUID interop with c# code

后端 未结 3 480
半阙折子戏
半阙折子戏 2021-02-11 09:22

Can c# donet generate same UUID for following java code? if so how? i tried GUID but didn\'t work!

Text:

String cleartext = \"CN=CompanyName;mac=some mac         


        
相关标签:
3条回答
  • 2021-02-11 09:53

    If all you need is the same UUID string (and not actual UUID/Guid objects), this C# method will return the same value as Java's UUID.nameUUIDFromBytes(byte[]) method.

    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# Example

    string test = "test";
    Console.Out.WriteLine(NameUUIDFromBytes(Encoding.UTF8.GetBytes(test)));
    
    Output:
    098f6bcd-4621-3373-8ade-4e832627b4f6
    

    Java Example

    UUID test = UUID.nameUUIDFromBytes("test".getBytes("UTF-8"));
    System.out.println(test);
    
    Output:
    098f6bcd-4621-3373-8ade-4e832627b4f6
    

    Edit: I know it's after the fact, but this will produce an actual Guid object with the same value. Just incase anyone wants it.

    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);
    }
    
    0 讨论(0)
  • 2021-02-11 10:11

    If you want interoperability don't depend on code that's not under your control. It could change with each Java version or implementation.

    You could take the way that is used

    /**
     * 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);
    }
    

    source

    and copy it into your code. Create exactly that in other languages as well and your problem should be gone.

    In case "type 3 (name based) UUID" is a standard where the result is exactly specified, you could skip copying it in Java since implementation should never return a different result. It's likely that you will find implementations for other languages as well and don't need to port it by hand.

    0 讨论(0)
  • 2021-02-11 10:15

    This code is definitely not going to work with .NET.

    The Guid(Byte[]) constructor must take in 16 bytes (as Guids are 128 bits), otherwise it will throw an ArgumentException. Your string is much more than 16 bytes.

    However, with that said, C# and Java will still not produce the same UUIDs using the same 16 bytes passed into the constructor. In Java, you can pass in any arbitrary number of bytes into the UUID constructor and it will create a hash of those bytes. In other words:

    In 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);
    

    Will produce a different value than:

    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);
    

    ...in Java.

    You could probably implement .NET's Byte[16] constructor in Java, or implement Java's hash constructor in .NET, but I would suggest using a string representation of your UUID across both platforms, for example, "190c4c10-5786-3212-9d85-018939108a6c".

    If you're trying to create a hash from a string, you might want to check into the MD5 class. You'd want something like:

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

    MD5 is a standard algorithm and will produce the same hash for the same string in both .NET and Java.

    0 讨论(0)
提交回复
热议问题