গোপন কীটি স্ট্রিং এবং ভাইস ভার্সায় রূপান্তর করা


102

আমি একটি কী তৈরি করছি এবং এটি ডিবিতে সঞ্চয় করা দরকার, তাই আমি এটিকে একটি স্ট্রিংয়ে রূপান্তর করি, তবে স্ট্রিং থেকে কীটি ফিরে পেতে। এটি সম্পাদনের সম্ভাব্য উপায়গুলি কী কী?

আমার কোডটি হ'ল,

SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);

আমি কীভাবে স্ট্রিং থেকে কীটি ফিরে পেতে পারি?


1
নোট করুন যে কীগুলির স্ট্রিংয়ে রূপান্তর কেবল তখনই করা উচিত যখন সম্পূর্ণ প্রয়োজন necessary Stringজাভাতে উদাহরণগুলি ধ্বংস করার জন্য কোনও সুস্পষ্ট পদ্ধতি নেই যখন মূল বিষয়গুলি এবং বাইট অ্যারেগুলি সাফ করা যেতে পারে। এর অর্থ হ'ল চাবিগুলি দীর্ঘ সময়ের জন্য মেমরির মধ্যে উপলব্ধ থাকতে পারে। একটি (পাসওয়ার্ড সুরক্ষিত) ব্যবহার KeyStoreকরে, রানটাইম সিস্টেম / ওএস বা এমনকি হার্ডওয়্যার দ্বারা সমর্থিত একটিকে পছন্দ করা উচিত।
মার্টেন বোদেউয়েস

উত্তর:


272

আপনি SecretKeyবাইট অ্যারে ( byte[]) এ রূপান্তর করতে পারেন , তারপরে বেস 64 এটিকে এন এ এনকোড করুন String। একটিতে ফিরে রূপান্তর করতে SecretKey, বেস 64 স্ট্রিংটি ডিকোড করে SecretKeySpecআপনার মূলটি পুনর্নির্মাণ করতে এটিতে ব্যবহার করুন SecretKey

জাভা 8 এর জন্য

স্ট্রিং থেকে সিক্রেটকি:

// create new key
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// get base64 encoded version of the key
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());

স্ট্রিং টু সিক্রেটকে:

// decode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// rebuild key using SecretKeySpec
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

জাভা 7 এবং এর আগে (অ্যান্ড্রয়েড সহ):

দ্রষ্টব্য আমি: আপনি বেস 64 এনকোডিং / ডিকোডিং অংশটি এড়াতে পারেন এবং কেবল byte[]এসকিউএলাইটে সঞ্চয় করতে পারেন । এটি বলেছে যে বেস 64 এনকোডিং / ডিকোডিং করা কোনও ব্যয়বহুল ক্রিয়াকলাপ নয় এবং আপনি সমস্যাগুলি ছাড়াই প্রায় কোনও ডিবিতে স্ট্রিং সংরক্ষণ করতে পারেন।

দ্রষ্টব্য II: পূর্ববর্তী জাভা সংস্করণগুলিতে একটি java.langবা java.utilপ্যাকেজগুলির মধ্যে একটি বেস 64 অন্তর্ভুক্ত নয় । তবে অ্যাপাচি কমন্স কোডেক , বাউন্সি ক্যাসেল বা পেয়ারা থেকে কোডেক ব্যবহার করা সম্ভব ।

স্ট্রিং থেকে সিক্রেটকি:

// CREATE NEW KEY
// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)

    SecretKey secretKey;
    String stringKey;

    try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
    catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}

    if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}

স্ট্রিং টু সিক্রেটকে:

// DECODE YOUR BASE64 STRING
// REBUILD KEY USING SecretKeySpec

    byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
    SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

@ জবাড়ি "বেস 64" শ্রেণীর জন্য প্যাকেজটি কী
অদলবদল করুন

পছন্দ করুন এই লিঙ্কটি দেখুন: ডেভেলপার.অ্যান্ড্রয়েড.
জাবারি

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

@ মার্টেনবোডেউস-আউলস্টেড আপনার মন্তব্যটি আমার প্রথম বাক্যটিকে সম্পূর্ণ উপেক্ষা করে: "বেশিরভাগ লোক এখনও জাভা 8 ব্যবহার করছে না"। আপনার উত্তরটি জাভা ব্যবহারকারীদের বিশাল সংখ্যক, অ্যান্ড্রয়েড এবং অ-অ্যান্ড্রয়েডের জন্য ব্যতিক্রম ত্রুটি ফেলে দেবে। এটি বলেছিল, আপনার বর্তমান উত্তর ছাড়াও একটি স্নিপেট যুক্ত করার পরামর্শটি আরও একটি সম্পূর্ণ সমাধান সরবরাহ করবে। এফওয়াইআই, আমি আমার উত্তরের প্রতি "সংবেদনশীল" নই। প্রকৃতপক্ষে, আমি এইএস এর জন্য ডিইএস বদলেছি কারণ এটি একটি সুনির্দিষ্ট উন্নতি সুরক্ষা অনুযায়ী (পাশাপাশি মূল প্রশ্নের কোডের সাথে আরও বেশি মিল রয়েছে)।
জাবারি

@ মার্টেনবোডওয়েস-আওলস্টেড আবার ... আপনি যা যুক্ত করেছেন তা "NoSuchAlgorithmException" ব্যতিক্রম ত্রুটি নিক্ষেপ করবে। দয়া করে দেখুন: docs.oracle.com/javase/7/docs/api/javax/crypto/… আমি ঠিক করব ...
জাবরী

5

দ্রুত ব্যর্থ হওয়া কিছু ফাংশন তৈরি করা কতটা মজাদার তা দেখানোর জন্য আমি নীচের 3 টি ফাংশন লিখেছি।

একটি একটি এইএস কী তৈরি করে, একটি এটিকে এনকোড করে এবং একটি এটিকে আবার ডিকোড করে। এই তিনটি পদ্ধতি জাভা 8 (অভ্যন্তরীণ শ্রেণীর নির্ভরতা বা বাইরের নির্ভরতা ছাড়াই) ব্যবহার করা যেতে পারে:

public static SecretKey generateAESKey(int keysize)
        throws InvalidParameterException {
    try {
        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new InvalidParameterException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(keysize);
        return keyGen.generateKey();
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static SecretKey decodeBase64ToAESKey(final String encodedKey)
        throws IllegalArgumentException {
    try {
        // throws IllegalArgumentException - if src is not in valid Base64
        // scheme
        final byte[] keyData = Base64.getDecoder().decode(encodedKey);
        final int keysize = keyData.length * Byte.SIZE;

        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES
        switch (keysize) {
        case 128:
        case 192:
        case 256:
            break;
        default:
            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
        }

        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new IllegalArgumentException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        // throws IllegalArgumentException - if key is empty
        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
        return aesKey;
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static String encodeAESKeyToBase64(final SecretKey aesKey)
        throws IllegalArgumentException {
    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {
        throw new IllegalArgumentException("Not an AES key");
    }

    final byte[] keyData = aesKey.getEncoded();
    final String encodedKey = Base64.getEncoder().encodeToString(keyData);
    return encodedKey;
}

2
নোট করুন যে কী স্টোরটি কোনও হার্ডওয়্যার সুরক্ষা মডিউলে (বা অন্য কোনও জায়গায় যেখানে getEncoded()উপলভ্য নয়) থাকে সেগুলি কী সংরক্ষণ করতে বা পুনরুদ্ধার করতে পারে না ।
মার্টেন বোদেউয়েস

1

আসলে লুইস যা প্রস্তাব করেছিলেন তা আমার পক্ষে কার্যকর হয়নি। আমি অন্য উপায় খুঁজে বের করতে হয়েছিল। এটিই আমাকে সাহায্য করেছিল। আপনাকেও সাহায্য করতে পারে লিঙ্ক:

  1. * .getEncoded (): https://docs.oracle.com/javase/7/docs/api/java/security/Key.html

  2. এনকোডার তথ্য: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

  3. ডিকোডার তথ্য: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html

কোড স্নিপেটস: এনকোডিংয়ের জন্য:

String temp = new String(Base64.getEncoder().encode(key.getEncoded()));

ডিকোডিংয়ের জন্য:

byte[] encodedKey = Base64.getDecoder().decode(temp);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "DES");

0

আপনি ব্যবহার করতে চান না .toString()

লক্ষ্য করুন যে সিক্রেটকি জাভা.সিকিউরিটি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে ey কে, যা নিজেই সিরিয়ালাইজেবল থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। সুতরাং এখানে কীটি (কোনও পাং উদ্দেশ্য নয়) কীটি বাইটআরআউটআউটপুট স্ট্রিমে ক্রমিক করা, বাইট [] অ্যারেটি পেয়ে ডিবিতে সংরক্ষণ করা store বিপরীত প্রক্রিয়াটি হ'ল বাইট [] ডিবি বন্ধ করে দেওয়া, বাইট [বায়ু অ্যারে থেকে একটি বাইটআররেইনপুট স্ট্রিম তৈরি করা, এবং এটি সিক্রেটকে অপসারণ করা ...

... বা আরও সহজ, .getEncoded()জাভা.সিকিউরিটি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত পদ্ধতিটি ব্যবহার করুন ey কে (যা সিক্রেটকি এর পিতামাতার ইন্টারফেস)। এই পদ্ধতিটি এনকোডড বাইট [] কী / সিক্রেটকি বন্ধ করে দেয়, যা আপনি ডাটাবেস থেকে সঞ্চয় বা পুনরুদ্ধার করতে পারবেন।

এটি সমস্ত আপনার সিক্রেটকি বাস্তবায়ন এনকোডিং সমর্থন করে। তা না হলে,getEncoded() নাল ফিরে আসবে।

সম্পাদনা:

আপনার কী / সিক্রেটকি জাভাদোকগুলি দেখতে হবে (একটি গুগল পৃষ্ঠার শুরুতে উপলব্ধ):

http://download.oracle.com/javase/6/docs/api/java/security/Key.html

অথবা এটি কোডআরঞ্চ থেকে (একই গুগল অনুসন্ধানের সাথেও পাওয়া যায়):

http://www.coderanch.com/t/429127/java/java/Convertion-between-SecretKey-String-or


সিরিয়ালাইজয়েবল হ'ল এই দিনগুলির আইএমও বিরোধী ধাঁচ যখনই আপনার বিকল্প বিকল্প রয়েছে। অনুমোদিত উত্তর যা বেস 64 এনকোড করে এবং ডিকোড করে এটি আরও ভাল।
ব্যবহারকারী 22303059

0

স্ট্রিং এবং ভাইস বিপরীতভাবে করার SecretKeySpec রূপান্তর: আপনি ব্যবহার করতে পারেন getEncoded()পদ্ধতিতে SecretKeySpecযা দেব byteArray, যা থেকে আপনি ব্যবহার করতে পারেন encodeToString()পেতে stringমান SecretKeySpecমধ্যেBase64 অবজেক্টের ।

রূপান্তর করার সময় SecretKeySpecথেকে String: ব্যবহার decode()মধ্যে Base64দেব byteArray, যে থেকে আপনার জন্য উদাহরণস্বরূপ তৈরি করতে পারেন SecretKeySpecপ্যারাম মত byteArrayআপনার পুনর্গঠন করা SecretKeySpec

String mAesKey_string;
SecretKeySpec mAesKey= new SecretKeySpec(secretKey.getEncoded(), "AES");

//SecretKeySpec to String 
    byte[] byteaes=mAesKey.getEncoded();
    mAesKey_string=Base64.encodeToString(byteaes,Base64.NO_WRAP);

//String to SecretKeySpec
    byte[] aesByte = Base64.decode(mAesKey_string, Base64.NO_WRAP);
    mAesKey= new SecretKeySpec(aesByte, "AES");

-1

এটি চেষ্টা করুন, এটি বেস 64 ছাড়া কাজ করে (এটি কেবল জেডিকে 1.8 এর অন্তর্ভুক্ত), এই কোডটি পূর্ববর্তী জাভা সংস্করণেও চালিত হয় :)

private static String SK = "Secret Key in HEX";


//  To Encrupt

public static String encrypt( String Message ) throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK);
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher c = Cipher.getInstance("DES","SunJCE");
    c.init(1, k);
    byte mes_encrypted[] = cipher.doFinal(Message.getBytes());

    String MessageEncrypted = byteArrayToHexString(mes_encrypted);
    return MessageEncrypted;
}

//  To Decrypt

public static String decrypt( String MessageEncrypted )throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK );
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher dcr =  Cipher.getInstance("DES","SunJCE");
    dc.init(Cipher.DECRYPT_MODE, k);
    byte[] MesByte  = hexStringToByteArray( MessageEncrypted );
    byte mes_decrypted[] = dcipher.doFinal( MesByte );
    String MessageDecrypeted = new String(mes_decrypted);

    return MessageDecrypeted;
}

public static String byteArrayToHexString(byte bytes[]){

    StringBuffer hexDump = new StringBuffer();
    for(int i = 0; i < bytes.length; i++){
    if(bytes[i] < 0)
    {   
        hexDump.append(getDoubleHexValue(Integer.toHexString(256 - Math.abs(bytes[i]))).toUpperCase());
    }else
    {
        hexDump.append(getDoubleHexValue(Integer.toHexString(bytes[i])).toUpperCase());
    }
    return hexDump.toString();

}



public static byte[] hexStringToByteArray(String s) {

    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2)
    {   
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
    }
    return data;

} 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.