2017-12-13 88 views
5

मैं गोलांग में एचओटीपी (आरएफसी -4226) को लागू करने की कोशिश कर रहा हूं और मैं वैध एचओटीपी उत्पन्न करने के लिए संघर्ष कर रहा हूं। मैं इसे जावा में उत्पन्न कर सकता हूं लेकिन कुछ कारणों से गोलांग में मेरा कार्यान्वयन अलग है।एचओटीपी के लिए जावा बनाम गोलांग (आरएफसी -4226)

public static String constructOTP(final Long counter, final String key) 
     throws NoSuchAlgorithmException, DecoderException, InvalidKeyException { 
    final Mac mac = Mac.getInstance("HmacSHA512"); 

    final byte[] binaryKey = Hex.decodeHex(key.toCharArray()); 

    mac.init(new SecretKeySpec(binaryKey, "HmacSHA512")); 
    final byte[] b = ByteBuffer.allocate(8).putLong(counter).array(); 
    byte[] computedOtp = mac.doFinal(b); 

    return new String(Hex.encodeHex(computedOtp)); 
} 

और जाओ में:

func getOTP(counter uint64, key string) string { 
    str, err := hex.DecodeString(key) 
    if err != nil { 
     panic(err) 
    } 
    h := hmac.New(sha512.New, str) 
    bs := make([]byte, 8) 
    binary.BigEndian.PutUint64(bs, counter) 
    h.Write(bs) 
    return base64.StdEncoding.EncodeToString(h.Sum(nil)) 
} 

मेरा मानना ​​है कि मुद्दा यह है कि जावा लाइन है: ByteBuffer.allocate(8).putLong(counter).array(); जाओ लाइन से एक अलग बाइट सरणी उत्पन्न करता है: यहाँ नमूने हैं binary.BigEndian.PutUint64(bs, counter)

जावा में, निम्न बाइट सरणी उत्पन्न होती है: 83 -116 -9 -98 115 -126 -3 -48 और गो में: 83 140 247 158 115 130 253 207

क्या किसी को दो पंक्तियों में अंतर पता है और मैं जावा लाइन को कैसे बंद कर सकता हूं?

उत्तर

10

जावा में byte प्रकार पर हस्ताक्षर किए है, यह है, जबकि जाओ byte में uint8 के उपनाम और 0..255 की एक श्रृंखला है, -128..127 की एक सीमा है। इसलिए यदि आप परिणामों की तुलना करना चाहते हैं, तो आपको 256 (256 जोड़ें) द्वारा नकारात्मक जावा मानों को स्थानांतरित करना होगा।

युक्ति: byteValue & 0xff जो int में सबसे कम 8 बिट के रूप में byte के 8 बिट का उपयोग कर int में बदल देता है: एक अहस्ताक्षरित फैशन, उपयोग में एक जावा byte मूल्य प्रदर्शित करने के लिए। या बेहतर: हेक्स रूप में दोनों परिणामों को प्रदर्शित ताकि आप साइन-सत्ता के बारे में देखभाल करने के लिए नहीं है ...

अपने नकारात्मक जावा बाइट मूल्यों को 256 जोड़ा जा रहा है, उत्पादन लगभग के जाने के लिए समान होता है: पिछले बाइट 1 से बंद है:

javabytes := []int{83, -116, -9, -98, 115, -126, -3, -48} 
for i, b := range javabytes { 
    if b < 0 { 
     javabytes[i] += 256 
    } 
} 
fmt.Println(javabytes) 

आउटपुट है:

[83 140 247 158 115 130 253 208] 

तो अपने जावा सरणी के अंतिम बाइट 208 है, जबकि जाओ के 207 है। मैं अनुमान लगा रहा हूं कि आपके counter को आपके कोड में कहीं और बढ़ाया गया है जिसे आपने पोस्ट नहीं किया है।

जावा में आप हेक्स एन्कोडेड परिणाम वापस करते हैं, जबकि आप बेस 64 एन्कोडेड परिणाम लौटाते हैं (वे 2 अलग-अलग एन्कोडिंग पूरी तरह अलग परिणाम देते हैं)। जैसा कि आपने पुष्टि की है, hex.EncodeToString(h.Sum(nil)) पर वापस लौटने के परिणाम परिणाम मिलते हैं।

टिप # 2: जाओ के बाइट्स एक हस्ताक्षरित फैशन में दिखाने के लिए, इस तरह int8 लिए उन्हें बदलने (जो हस्ताक्षरित किया गया है):

gobytes := []byte{83, 140, 247, 158, 115, 130, 253, 207} 
for _, b := range gobytes { 
    fmt.Print(int8(b), " ") 
} 

यह आउटपुट:

83 -116 -9 -98 115 -126 -3 -49 
+0

वास्तव में, 'uint8 (-48)' 208 है, 207 नहीं (https://play.golang.org/p/marMBd3rwg) – JimB

+0

@JimB आप सही हैं, अंतिम बाइट मेल नहीं खाता है। – icza

+1

वाह - टीआईएल! व्यस्त ऑपरेशन क्या होगा? (गो संस्करण लेना और जावा संस्करण बनाना)। आपका बहुत बहुत धन्यवाद! –

संबंधित मुद्दे