জাভা স্ট্রিং থেকে এসএএএ 1


158

আমি জাভাতে SHA1 রূপান্তরকারীকে একটি সাধারণ স্ট্রিং তৈরি করার চেষ্টা করছি এবং এটি আমার কাছে ...

public static String toSHA1(byte[] convertme) {
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA-1");
    }
    catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    } 
    return new String(md.digest(convertme));
}

যখন আমি এটা পাস toSHA1("password".getBytes()), আমি পেতে [�a�ɹ??�%l�3~��.আমি জানি এটা সম্ভবত হল UTF-8 মত সরল এনকোডিং ফিক্স, কিন্তু কেউ তো এটুকু কি আমি কি চাই যা পেতে কি করা উচিত পারে5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 ? নাকি আমি এটা পুরোপুরি ভুল করছি?


অ্যালগোরিদম SHA1হাইফেন ছাড়াই, জানেন না যে এটি কোনও পার্থক্য করবে কিনা।
স্ক্র্যাম মিস্টার

আপনি কল করার সময় অক্ষর এনকোডিং নির্দিষ্ট করা ভাল অনুশীলন getBytes(), উদাহরণস্বরূপ ব্যবহার করুনtoSHA1("password".getBytes("UTF-8"))
Qwerky

উত্তর:


183

আপডেট
আপনি আপনার জন্য এই কাজটি করতে অ্যাপাচি কমন্স কোডেক (সংস্করণ 1.7+) ব্যবহার করতে পারেন।

DigestUtils.sha1Hex (stringToConvertToSHexRepresentation)

এই পরামর্শের জন্য @ জোন অনস্টটকে ধন্যবাদ ।


পুরানো উত্তর
আপনার বাইট অ্যারেটিকে হেক্স স্ট্রিংয়ে রূপান্তর করুন। রিয়েল এর কিভাবে আপনাকে জানায় কিভাবে

return byteArrayToHexString(md.digest(convertme))

এবং (রিয়েল কীভাবে তা অনুলিপি করেছেন)

public static String byteArrayToHexString(byte[] b) {
  String result = "";
  for (int i=0; i < b.length; i++) {
    result +=
          Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
  }
  return result;
}

বিটিডাব্লু, আপনি বেস 64 ব্যবহার করে আরও কমপ্যাক্ট উপস্থাপনা পেতে পারেন। অ্যাপাচি কমন্স কোডেক এপিআই 1.4 এর সমস্ত ব্যথা দূর করার জন্য এই দুর্দান্ত উপযোগিতা রয়েছে। এখানে উল্লেখ করুন


4
বেস 64 এবং sha1 খুব আলাদা - বিকল্প হিসাবে তাদের পরামর্শ করবেন না।
রায়ান এ।

13
@ রায়না: যেমন আমি এটি বুঝতে পারি, তিনি বেস 64 কে এসএএএ 1 হ্যাশ হ্যাক্স-এনকোডিংয়ের বিকল্প হিসাবে প্রস্তাব করেছেন (সম্পূর্ণরূপে এসএইএ 1 এর বিকল্প হিসাবে নয়)।
হেলবার্ট

আমি এখনও এটি চেষ্টা করি নি, তবে আপনি কীভাবে এটি কাজ করে তা বোঝানোর যত্ন নেবেন?
জিভায়ে

11
DigestUtils.sha1Hex("my string")চাকাটিকে পুনরায় উদ্ভাবনের পরিবর্তে লাইব্রেরি কেন ব্যবহার করবেন না (যদিও কীভাবে হাতের মাধ্যমে হেক্সে রূপান্তর করবেন তা জানা আকর্ষণীয়)?
জন অনস্টট

3
কারণ যখন এই উত্তরটি ডাইজেস্টটিলগুলি লেখা হয়েছিল (সেপ্টেম্বর ২০১২ সালে 1.7 প্রকাশিত হয়েছিল) সেই বৈশিষ্ট্যটি ছিল না। এই বিষয়টি চিহ্নিত করার জন্য ধন্যবাদ. +1
নিশান্ত

67

এটি আমার স্ট্রিংকে sha1 এ রূপান্তর করার সমাধান। এটি আমার অ্যান্ড্রয়েড অ্যাপে ভাল কাজ করে:

private static String encryptPassword(String password)
{
    String sha1 = "";
    try
    {
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(password.getBytes("UTF-8"));
        sha1 = byteToHex(crypt.digest());
    }
    catch(NoSuchAlgorithmException e)
    {
        e.printStackTrace();
    }
    catch(UnsupportedEncodingException e)
    {
        e.printStackTrace();
    }
    return sha1;
}

private static String byteToHex(final byte[] hash)
{
    Formatter formatter = new Formatter();
    for (byte b : hash)
    {
        formatter.format("%02x", b);
    }
    String result = formatter.toString();
    formatter.close();
    return result;
}

7
সতর্কতা এড়ানোর জন্য এটি java.util. Formatter এবং শেষে একটি ফর্ম্যাটারক্লোজ () দরকার তা নির্দিষ্ট করতে পারে।
এরিক চেন

শোডল encryptPassword("test")এবং echo test|sha1sumলিনাক্স টার্মিনাল আউটপুটে একই ফলাফল নয়? তারা না।
তুলিনাস কর্ডোভা

@ টুলিনস কর্ডোভা কনসোলের অনুরোধ সম্পর্কিত: আপনি যদি ব্যবহার করেন echo testতবে লাইন ব্রেক সহ আউটপুটটি পাইপ করা হবে sha1sum। আপনি লাইন বিরতি trailing ছাড়া একটি প্লেইন স্ট্রিং হ্যাশ চান, আপনি ব্যবহার করতে পারেন echo -n test | sha1sum-nপরামিতি তোলে echoলাইন বিরতি বাদ।
মিঃসনরব

প্রশ্নের তুলনায় কম, তবে সাধারণভাবে: আপনার encryptPassword()শব্দগুলি প্রমাণীকরণ ডেটা সংরক্ষণ করার জন্য ব্যবহার করা হচ্ছে বলে মনে হচ্ছে। নোট করুন যে আপনার কোডিংটি অভিধান আক্রমণগুলিতে ঝুঁকিপূর্ণ, কারণ কোনও বীজ প্রয়োগ করা হয়নি। এটি আপনার অ্যাপ্লিকেশনের জন্য সমস্যা কিনা আপনার সুরক্ষা পরিবেশ পরীক্ষা করে দেখুন!
agগলরেণবো

54

পেয়ারা হ্যাশিং ক্লাস ব্যবহার করা :

Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString()

1
এই উত্তরের একটি আপডেটের প্রয়োজন হতে পারে কারণ এটি এখন একটি সতর্কতা তৈরি করবে যে হ্যাশিং অস্থির।
সেমির দেলজিć

32

SHA-1 (এবং অন্যান্য সমস্ত হ্যাশিং অ্যালগরিদম) বাইনারি ডেটা ফেরত দেয়। তার মানে যে (জাভাতে) তারা একটি উত্পাদন করে byte[]। এই byteঅ্যারেটি কোনও নির্দিষ্ট অক্ষরের প্রতিনিধিত্ব করে না , যার অর্থ আপনি এটিকে কেবল নিজের Stringমতো করে রূপান্তর করতে পারবেন না ।

আপনার যদি প্রয়োজন হয় Stringতবে আপনাকে সেটিকে byte[]এমনভাবে বিন্যাস করতে হবে যা উপস্থাপিত হতে পারে String(অন্যথায়, কেবল byte[]চারপাশে রাখুন)।

byte[]মুদ্রণযোগ্য অক্ষর হিসাবে নির্বিচারে উপস্থাপনের দুটি সাধারণ উপায় হ'ল BASE64 বা সাধারণ হেক্স-স্ট্রিংস (অর্থাত্ প্রতিটি উপস্থাপন করে)byte দুটি হেক্সাডেসিমাল অঙ্ক দ্বারা )। দেখে মনে হচ্ছে আপনি হেক্স-স্ট্রিং তৈরি করার চেষ্টা করছেন।

আরও একটি সমস্যা রয়েছে: আপনি যদি কোনও জাভা এর SHA-1 পেতে চান Stringতবে আপনাকে প্রথমে রূপান্তর করতে Stringহবে byte[](SHA-1 এর ইনপুটটিও byte[]পাশাপাশি)। আপনি যদি কেবল myString.getBytes()যেমনটি দেখান তেমনভাবে ব্যবহার করেন তবে এটি প্ল্যাটফর্মের ডিফল্ট এনকোডিংটি ব্যবহার করবে এবং এটি আপনার চালিত পরিবেশের উপর নির্ভর করবে (উদাহরণস্বরূপ এটি আপনার ওএসের ভাষা / স্থানীয় সেটিং এর উপর ভিত্তি করে বিভিন্ন ডেটা ফেরত দিতে পারে)।

একটি ভাল সমাধান জন্য ব্যবহার করতে এনকোডিং উল্লেখ হয় String-to- byte[]ভালো রূপান্তর: myString.getBytes("UTF-8")। ইউটিএফ -8 (বা অন্য এনকোডিং যা প্রতিটি ইউনিকোডের চরিত্রকে উপস্থাপন করতে পারে) নির্বাচন করা এখানে নিরাপদ পছন্দ।


27

এটি একটি সহজ সমাধান যা স্ট্রিংকে হেক্স ফর্ম্যাটে রূপান্তর করার সময় ব্যবহার করা যেতে পারে:

private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {

    MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    crypt.reset();
    crypt.update(password.getBytes("UTF-8"));

    return new BigInteger(1, crypt.digest()).toString(16);
}

সতর্কতা: হ্যাশ জেনারেশন '0' দিয়ে শুরু করা হ্যাশগুলির জন্য ভুল। আপনি 39 টি অক্ষর সহ একটি স্ট্রিং পাবেন।
ফিল্নন

@ ফিলান আপনি সমাধানের পরামর্শ দিতে পারেন?
নিকিতা কোকশারভ

1
আমি অনুমান করি যে আপনি যদি পর্যাপ্ত নেতৃস্থানীয় শূন্যগুলি সহ একটি বাইট [] থেকে একটি বড় পূর্ণসংখ্যা তৈরি করেন তবে এই 0 টি হারিয়ে যায়। সুতরাং, হেক্স স্ট্রিং প্রতিনিধিত্ব "0" সেখানে থাকবে না, 39 বা তার চেয়ে কম অক্ষর সহ একটি হ্যাশ নিয়ে যাবে। আমি উপরে পেট্রনোহেলস সমাধান ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করে ...
ফিলি্ন

25

কেবল অ্যাপাচি কমন্স কোডেক লাইব্রেরি ব্যবহার করুন। ডাইজেস্টটিলস নামে তাদের একটি ইউটিলিটি ক্লাস রয়েছে

বিস্তারিত জানার দরকার নেই।


51
আমি দ্বিমত পোষণ করছি, বিশদ বিবরণটি পাওয়া পুরো বিষয়টিকে সাজানো
55

12
আপনার কাছে বিশদ নেওয়ার সময় আছে কিনা তা প্রশ্ন। পুরো পয়েন্টটি সাধারণত এটি সময়মতো করা হয়। প্রত্যেকেই শিক্ষার্থী নয় বা সমস্ত বিবরণ শেখার বিলাসিতা রয়েছে।
দ্যাট্রুপ

ডাইজেস্টটিলস একটি বাইট অ্যারে প্রদান করে যাতে আপনার এটির Hex.encodeHexString এর মাধ্যমে চালনার প্রয়োজন স্ট্রিং প্রতিনিধিত্ব পেতে। জাভা: এটি ২০১৪ এবং আমাদের এখনও একটি পদক্ষেপ

5
একটি পদক্ষেপ SHA-1 পদ্ধতি: String result = DigestUtils.sha1Hex("An input string")ও o)
জন অনস্টট

18

যেমন অ্যাপাচি কমন্স কোডেক ব্যবহারের আগে উল্লেখ করা হয়েছে। এটি বসন্তের ছেলেরা দ্বারাও সুপারিশ করা হয়েছে (স্প্রিং ডকের ডাইজেস্টটিলগুলি দেখুন)। উদাহরণ:

DigestUtils.sha1Hex(b);

এখানে অবশ্যই শীর্ষ রেট দেওয়া উত্তর ব্যবহার করা হবে না।


6

এটি সঠিকভাবে মুদ্রণ করছে না কারণ আপনাকে বেস 64 এনকোডিং ব্যবহার করতে হবে। জাভা 8 এর সাথে আপনি বেস 64 এনকোডার শ্রেণিটি ব্যবহার করে এনকোড করতে পারেন ।

public static String toSHA1(byte[] convertme) {
    md = MessageDigest.getInstance("SHA-1");
    return Base64.getEncoder().encodeToString((md.digest(convertme));
}

ফলাফল

এটি আপনাকে আপনার প্রত্যাশিত আউটপুট দেবে 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8


1
@ দেবেনভ এটি তিনটি বিন্দু শ্যা -1 এর অর্থ এটি তার মূল কোডটি বজায় রাখবে যা শে 1 এ রূপান্তরিত হয়। স্ট্রিংটি সঠিকভাবে মুদ্রণের সময় ওপির মূল সমস্যা ছিল।
এডুয়ার্ডো ডেনিস

4

বার্তা ডাইজেস্ট (হ্যাশ) বাইট [] বাইটে [] বাইরে

একটি বার্তা হজম একটি ফাংশন হিসাবে সংজ্ঞায়িত করা হয় যা কাঁচা বাইট অ্যারে নেয় এবং একটি কাঁচা বাইট অ্যারে (ওরফে byte[]) প্রদান করে। উদাহরণস্বরূপ SHA-1 (সিকিওর হ্যাশ অ্যালগরিদম 1) এর ডাইজেস্ট আকার 160 বিট বা 20 বাইট রয়েছে। কাঁচা বাইট অ্যারে সাধারণত হিসাবে ব্যাখ্যা করা যায় না ইউটিএফ -8 এর মতো অক্ষর এনকোডিং না, কারণ প্রতিটি ক্রমের প্রতিটি বাইট আইনী নয় যা এনকোডিং। সুতরাং এগুলিকে এর সাথে রূপান্তর করা String:

new String(md.digest(subject), StandardCharsets.UTF_8)

কিছু অবৈধ সিক্যুয়েন্স তৈরি করতে পারে বা ইউনিকোড ম্যাপিংকে অপরিজ্ঞাত করতে কোড-পয়েন্টার থাকতে পারে :

[�a�ɹ??�%l3~��.

বাইনারি থেকে পাঠ্য এনকোডিং

এর জন্য বাইনারি-থেকে-পাঠ্য এনকোডিং ব্যবহৃত হয়। হ্যাশ সহ, সবচেয়ে বেশি ব্যবহৃত হয় হেক্স এনকোডিং বা বেস 16 । মূলত একটি বাইট থেকে মান থাকতে পারে 0জন্য 255(অথবা -128যাওয়ার 127যার HEX উপস্থাপনা সমতূল্য সাইন ইন)0x00 - 0xFF। সুতরাং হেক্স আউটপুটটির প্রয়োজনীয় দৈর্ঘ্য দ্বিগুণ করবে, এর অর্থ একটি 20 বাইট আউটপুট একটি 40 অক্ষর দীর্ঘ হেক্স স্ট্রিং তৈরি করবে, যেমন:

2fd4e1c67a2d28fced849ee1bb76e7391b93eb12

মনে রাখবেন এটি হেক্স এনকোডিং ব্যবহার করার প্রয়োজন নেই। আপনি বেস 64 এর মতো কিছু ব্যবহার করতে পারেন । হেক্স প্রায়শই পছন্দ করা হয় কারণ এটি মানুষের দ্বারা সহজেই পাঠযোগ্য এবং প্যাডিংয়ের প্রয়োজনীয়তা ছাড়াই নির্ধারিত আউটপুট দৈর্ঘ্য রয়েছে has

আপনি একা জেডিকে কার্যকারিতা সহ বাইট অ্যারে হেক্সে রূপান্তর করতে পারেন:

new BigInteger(1, token).toString(16)

নোট যাইহোক এটি BigIntegerপ্রদত্ত বাইট অ্যারের সংখ্যা হিসাবে এবং বাইট স্ট্রিং হিসাবে নয় হিসাবে ব্যাখ্যা করবে । তার অর্থ নেতৃস্থানীয় শূন্যগুলি আউটপুট করা হবে না এবং ফলস্বরূপ স্ট্রিং 40 টি অক্ষরের চেয়ে কম হতে পারে।

এইচএক্স-এ এনকোড করতে গ্রন্থাগারগুলি ব্যবহার করা হচ্ছে

আপনি এখন স্ট্যাক ওভারফ্লো থেকে একটি অচিহ্নিত বাইট-টু-হেক্স পদ্ধতি অনুলিপি এবং পেস্ট করতে পারেন বা পেয়ারা জাতীয় বিশাল নির্ভরতা ব্যবহার করতে পারেন

বেশিরভাগ বাইট সম্পর্কিত সমস্যাগুলির সমাধানের জন্য আমি এই কেসগুলি পরিচালনা করার জন্য একটি ইউটিলিটি প্রয়োগ করেছি: বাইটস-জাভা (গিথুব)

আপনার বার্তা ডাইজেস্ট বাইট অ্যারে রূপান্তর করতে আপনি ঠিক করতে পারেন

String hex = Bytes.wrap(md.digest(subject)).encodeHex();

অথবা আপনি কেবল বিল্ট-ইন হ্যাশ বৈশিষ্ট্যটি ব্যবহার করতে পারেন

String hex =  Bytes.from(subject).hashSha1().encodeHex();

2

বেস 64 SHA1হ্যাশের প্রতিনিধিত্ব :

String hashedVal = Base64.getEncoder().encodeToString(DigestUtils.sha1(stringValue.getBytes(Charset.forName("UTF-8"))));

1

এটি কাজ না করার কারণটি হ'ল আপনি যখন ফোন করবেন তখন আপনি String(md.digest(convertme))জাভাটিকে এনক্রিপ্ট করা বাইটের ক্রমকে স্ট্রিং হিসাবে ব্যাখ্যা করতে বলছেন। আপনি যা চান তা হ'ল বাইটগুলি হেক্সাডেসিমাল অক্ষরে রূপান্তর করা।


0

বাইট অ্যারে হেক্স স্ট্রিংয়ে রূপান্তর করুন।

public static String toSHA1(byte[] convertme) {
    final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA-1");
    }
    catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    byte[] buf = md.digest(convertme);
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i) {
        chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
        chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    }
    return new String(chars);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.