【问题标题】:C# Hash Bytes to Java -- Converting SQL Server HashBytes to JavaC# HashBytes to Java -- 将 SQL Server HashBytes 转换为 Java
【发布时间】:2014-05-12 15:05:52
【问题描述】:

寻求将 C# 代码转换为 Java 的帮助

我有字节数组,但需要帮助编码转换为 BigInteger。 希望为 Hadoop 创建 UDF;

C# 代码 输出,这和SQL Server一样

//A4-B7-83-01-00-59-25-A8-B5-7C-F7-16-E6-69-CF-14-A2-2E-22-09
//-6330555844639082588

// Unicode
byte[] byteArray = Encoding.UTF8.GetBytes("JAO21V279RSNHYGX23L0");
//Console.WriteLine(byteArray);
System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] hashedPasswordBytes = sha.ComputeHash(byteArray);
//Console.WriteLine(hashedPasswordBytes);
Console.WriteLine("1: " + BitConverter.ToString(hashedPasswordBytes));
//Console.WriteLine(BitConverter.ToInt64(hashedPasswordBytes,0));
long value = BitConverter.ToInt64(hashedPasswordBytes, 0);
Console.WriteLine("2: " + value);
if (BitConverter.IsLittleEndian)
    Array.Reverse(hashedPasswordBytes);
Console.WriteLine("3: " + BitConverter.ToString(hashedPasswordBytes));
value = BitConverter.ToInt64(hashedPasswordBytes, 0);
Console.WriteLine("4: " + value);

1: A4-B7-83-01-00-59-25-A8-B5-7C-F7-16-E6-69-CF-14-A2-2E-22-09 2:-6330555844639082588 翻转值 3:09-22-2E-A2-14-CF-69-E6-16-F7-7C-B5-A8-25-59-00-01-83-B7-A4 4: -1843714884904279543 -- 正确的 BigInt

SQL Server 代码

DECLARE @InputString VARCHAR(MAX) = 'JAO21V279RSNHYGX23L0'

SELECT CONVERT(BIGINT, HashBytes('SHA1', @InputString)) , HashBytes('SHA1', @InputString)

-1843714884904279543 0xA4B78301005925A8B57CF716E669CF14A22E2209

Java 输出 strHash:1a41b71831011001591251a81b517c1f71161e61691cf1141a212e122109

我目前拥有的 Java 代码 导入 java.nio.ByteBuffer; 导入 java.nio.ByteOrder; 导入 java.security.MessageDigest; 导入 java.security.NoSuchAlgorithmException; 导入java.lang.System.*; 导入静态 java.lang.System.out; 导入 java.math.BigInteger; 导入 java.nio.charset.Charset;

class JceSha1Test {

  private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");

  public static void main(String[] a) {
      try {
        String strHash = "JAO21V279RSNHYGX23L0";        
        strHash = encryptPassword(strHash);        
        System.out.println("strHash: " + strHash);
      } catch (Exception e) {
         System.out.println("Exception: "+e);
      }
   }
  public static String encryptPassword(String password) {
    String returnValue = null;
    byte[] buf = password.getBytes(UTF8_CHARSET);

    ByteBuffer bb = ByteBuffer.wrap( buf );
    MessageDigest algorithm=null;
    try {
      algorithm = MessageDigest.getInstance("SHA-1");

    } catch (NoSuchAlgorithmException e) {
      //sClassLog.logException(e);
    }
    algorithm.reset();
    algorithm.update(buf);
    byte[] digest = algorithm.digest();
    returnValue = "";

    for (int byteIdx = 0; byteIdx < digest.length; byteIdx++) {
      //System.out.println( Integer.toHexString(digest[byteIdx]) );
      //returnValue += Integer.toHexString(digest[byteIdx] + 256  & 0xFF);
      //returnValue += Integer.toHexString((digest[byteIdx] + 256   & 0xFF) + 0x100 );
      //returnValue += Integer.toHexString( ( digest[byteIdx] & 255 ) );
      //returnValue += Integer.toHexString( ( 0xFF & digest[byteIdx] ) );
      //returnValue += Integer.toHexString( ( digest[byteIdx] & 0xFF ) );      
      returnValue += Integer.toString( ( digest[byteIdx] & 0xFF ) + 0x100, 16).substring( 1 );      
      //returnValue += Integer.toHexString( ( digest[byteIdx] + 256 ) ); // Orig
    }
    return returnValue;    
  }
//A4-B7-83-01-00-59-25-A8-B5-7C-F7-16-E6-69-CF-14-A2-2E-22-09
//-1843714884904279543
}

感谢您的帮助!

///////////////////////********************** *********//////////////////////

我的最终代码与 SQL Server 中的 HashBytes 匹配:

package com.cb.hiveudf;

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.security.MessageDigest; 
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.LongWritable;


/**
 * Implementation of the HashBytes UDF found in many databases.
 */

@Description(name = "hashBytes", 
    value = "_FUNC_(Charset, Value) - assigns a unique Biginterger to each string to which it is applied",
    extended = "Example:\n "
    + "  > SELECT name, _FUNC_(\"UTF-16LE\", value) hashkey FROM src" + "  ")

public class UDFHashBytes extends UDF {
 private final LongWritable result = new LongWritable(); 

    public LongWritable evaluate(Text input) throws Exception {
        if (input == null) 
        {
              return null;
        } 
        else 
        {
            String hashstring = input.toString();
            byte[] buf = hashstring.getBytes("UTF-8");
            MessageDigest algorithm=null;
            algorithm = MessageDigest.getInstance("SHA-1");          
            algorithm.reset();
            algorithm.update(buf);
            byte[] digest = algorithm.digest();  
            if(java.nio.ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
              for (int i = 0, j = digest.length - 1; i < j; i++, j--)  
              {  
                byte b = digest[i];  
                digest[i] = digest[j];  
                digest[j] = b;  
              } 
            }    
            ByteBuffer bb = ByteBuffer.wrap( digest );
            if(java.nio.ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) 
            {
              bb.order(ByteOrder.LITTLE_ENDIAN);
            }    

            result.set(bb.getLong());
            return result;
        }
    }
}

【问题讨论】:

    标签: c# java sql-server cryptography


    【解决方案1】:

    好吧,我希望你还能认出一些代码:)

    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.nio.charset.StandardCharsets;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    final class JceSha1Test {
        public static void main(final String ... args) {
            final String strHashInput = "JAO21V279RSNHYGX23L0";
            final byte[] strHash = hashPassword(strHashInput);
            System.out.println("strHash: " + toHex(strHash));
            final ByteBuffer strHashBuffer = ByteBuffer.wrap(strHash);
            strHashBuffer.order(ByteOrder.LITTLE_ENDIAN);
            final long test = strHashBuffer.getLong();
            System.out.println(test);
        }
    
        public static byte[] hashPassword(final String password) {
            final byte[] encodedPassword = password.getBytes(StandardCharsets.UTF_8);
            final MessageDigest algorithm;
            try {
                algorithm = MessageDigest.getInstance("SHA-1");
            } catch (final NoSuchAlgorithmException e) {
                throw new IllegalStateException(e);
            }
            return algorithm.digest(encodedPassword);
        }
    
        public static String toHex(final byte[] data) {
            final StringBuilder sb = new StringBuilder(data.length * 2);
            for (int i = 0; i < data.length; i++) {
                sb.append(String.format("%02X", data[i]));
            }
            return sb.toString();
        }
    }
    

    【讨论】:

    • 请注意,仅保留 64 位(Java long 的大小)的散列通常被认为是不安全的。散列至少应为 160 位,即 SHA-1 的大小。所以我不知道你想用这个值做什么,但要小心!
    • 谢谢!只需使用它来散列一个 20 个字符的字符串作为数据库键。
    • 好的,没关系,但请注意,在大约 10 亿个(美国)字符串中,有一个 2.3% chance of collision,并且在 10 倍时,您有 97% 的碰撞机会,因为birthday problem。所以不要将它用于大量输入字符串。
    【解决方案2】:

    SQL 使用 bigEndin,但 C#(和其他语言)使用 Little Endian 作为 GetBytes。因此,在 GetBytes 之后反转结果。

     static long ComputeSha256HashbigInt(string rawData)
        {
            // Create a SHA256   
            using (SHA256 sha256Hash = SHA256.Create())
            {
                // ComputeHash - returns byte array  
                byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
    
                if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
    
                long value = BitConverter.ToInt64(bytes, 0);
    
                return value;
            }
        }
    

    【讨论】:

    • 感谢您的光临我发现我应该发布更新的代码:)
    猜你喜欢
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多