xor בג'אווה

nocgod

New member
סתם לידע כללי

מילות החיפוש
BigInteger Java from hex
BigInteger Java xor
הביאו לי 100% מהמידע שהייתי צריך כדי לכתוב את הקוד הזה...אני מאמין שגם אתה יכלת לחפש את זה ולמצוא...פשוט כמו שאמרת אתה מחפש את הדרך הפשוטה בלי הרבה סיבוכים
ומה יותר קל מלמצוא מישהו שיכתוב את זה בשבילך אה?
 

קונדסבא

New member
כנראה שלא מימשתי נכון

אמרתי לך, מצאתי את הפיתרון של bigInteger אבל בגלל שהיו לי הרבה המרות בין משתנים שונים כנראה שטעיתי במשהו במהלך המימוש ולא קיבלתי את תוצאת הxor הרצויה ואז גם באחת ההודעות ראיתי שיש שני סוגים שונים של xor (ביטוויס ולוג'יק??) וכבר לא היה לי כוח להתעמק בזה אז הגעתי לפה בתקווה למצוא איזה ספריה מוכנה שמחכה לי:)
 

nocgod

New member
XOR יש רק אחד

פעולת XOR מוגדרת בתורת הלוגיקה לפי טבלת האמת הזאת.
מה שבתחלס קורה כשאתה עושה XOR זה המרה לביטים, עשיית XOR פר ביט (ולכן bitwise) המרה בחזרה לבסיס הקודם (נניח בסיס 10)
XOR היא פעולה לוגית המוגדרת על בסיס 2 בדיוק כמו AND, OR, NAND, NOT וכו'...
אופרטורים שעובדים על הביטים של המשתנים נקראים bitwise operators וביניהם ניתן למצוא את: & | ! ^ וכמובן צירופים כמו NAND שזה not and או xor שזה exclusive or שמוגדר כאמת
כאשר רק אחד אמת והשני שקר.

לא יודע על איזה המרות אתה מדבר, אם הסתבכת בלקרוא את הdocumentation והדוגמאות של BigInteger אולי כדאי לך לקחת צעד אחורה ו:
* למצוא קצת סבלנות לקרוא דוגמאות ו documentation, הרבה מאוד מהקוד שתפתח יהיה קיים בחתיכות באינטרנט החוכמה זה לדעת למצוא אותן ולחבר
* לפרק בעיה לתת בעיות, פיתרון של תת הבעיות וחיבורן יביא לך פיתרון של הבעיה הכללית
* להבין את הבעיה, ולדעת לעשות לבעיה אבסטרקציה - להוריד את כל הטפל (תפל?) וכמובן להשתמש בנקודה הקודמת כדי לפתור את הבעיה האבסטרקטית
* אם יש בעיה בהבנת הנקרא - לחזק אנגלית, בלי זה לעולם לא תצליח.
 

קונדסבא

New member
תודה! עוד עזרה קטנה ואני מסיים

הצלחתי לפענח 2 מתוך 3 הבלוקים של ההודעה שאני צריך. משום מה הבלוק האחרון זורק לי אקספשן:
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes


השורה היא:
encrypt.doFinal(new BigInteger("fb94ffe0c5da05d9476be028ad7c1d81",16).toByteArray());

למה הוא טוען שהמחרוזת "fb94ffe0c5da05d9476be028ad7c1d81" היא לא 16 bytes??
 

nocgod

New member
נו מה עם לחפש קצת לבד?

אחי אנשים פותרים את niantic project בזמנם הפנוי ואתה לא יכול להזין בגוגל שורת חיפוש?
תחפש
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
בגוגל
התוצאה הראשונה (אצלי) הייתה
http://stackoverflow.com/questions/...izeexception-input-length-must-be-multiple-of
תקרא קצת, תגלול קצת למטה ותראה פיתרון.
 

קונדסבא

New member
שוב

חיפשתי לבד...ולא מצאתי תשובה. גם בלינק שלך לא הצלחתי למצוא תשובה. אני לא משתמש בpadded chiper ולא השתמשתי בgetbytes.
 

nocgod

New member
ואתה חושב אנחנו פה בעלי יכולות טלפטיות?

תראה קצת קוד, תראה מה ניסית, בינתיים אנחנו נותנים לך תשובות מהאוויר.
מה הבאת שורת קוד ואתה מצפה שאני אבין מה הולך לפניכן?
בstackoverflow שאלה שבנויה כמו השאלות שלך היו נסגרות מידית.
 

קונדסבא

New member
בעיקרון השורה שהבאתי היא הבעייתית

אני מודה, הקוד המלא מבולגן ומגעיל...בגלל שאני בונה את התוכנית רק בשביל לפענח הודעה ספציפית עשיתי הרבה קיצורי דרך והוא לא הכי קריא.
אבל בעיקרון זה רק השורה הזאת ספציפית עושה לי בעיות אז אני אנסה לחלץ אותה משאר הקוד-

SecretKeySpec key1 = new SecretKeySpec(new BigInteger(
"140b41b22a29beb4061bda66b6747e14", 16).toByteArray(), "AES");

Cipher encrypt = Cipher.getInstance("AES/ECB/NoPadding");
encrypt.init(Cipher.DECRYPT_MODE, key1);
encrypt.doFinal(new BigInteger("fb94ffe0c5da05d9476be028ad7c1d81",16).toByteArray()); //<==this is the madafaqa problematic line


כשאני מחליף את השורה הנ"ל למשל במחרוזת: 28a226d160dad07883d04e008a7897ee הכל עובד חלק...אבל עם המחרוזת הנוכחית זה זורק לי את האקספשן המדובר.
 

קונדסבא

New member
אני רק אוסף שכל המחלקות הם מחלקות של ג'אווה

לא מימשתי כלום...הכל javax.crypto
 

nocgod

New member
נו...במקום לשבור את הראש עם biginteger פה

פשוט תשמש בgetBytes וזהו
מה אמורה להיות התוצאה?
byte[] encrypted = encrypt.doFinal("fb94ffe0c5da05d9476be028ad7c1d81".getBytes()); //<==this is the madafaqa problematic line
זה מתקמפל
וכשאני מנסה להעביר את זה לstring אני מקבל חירטוטים

קח בחשבון שיש לך פה מפתח באורך 32 בתים, והבנתי שג'אווה לא עושה בעיות עם מפתחות ארוכים יותר מ 16 בתים או משהו כזה...אולי אתה עושה משהו לא נכון ואנחנו לא יודעים מזה בכלל...
 

nocgod

New member
שים לב למה יהיה הפלט בהרצה

SecretKeySpec key1 = new SecretKeySpec(new BigInteger("140b41b22a29beb4061bda66b6747e14", 16).toByteArray(), "AES");

Cipher encrypt = Cipher.getInstance("AES/ECB/NoPadding");
System.out.println("max aes length: " + Cipher.getMaxAllowedKeyLength("AES") + "bits");
encrypt.init(Cipher.DECRYPT_MODE, key1);
byte[] encrypted = encrypt.doFinal("fb94ffe0c5da05d9476be028ad7c1d81".getBytes()); //<==this is the madafaqa problematic line

BigInteger bi = new BigInteger(encrypted);
System.out.println(bi);

שים לב גם שאם אני משנה את השורה הראשונה ל:

SecretKeySpec key1 = new SecretKeySpec("140b41b22a29beb4061bda66b6747e14".getBytes(), "AES");

אתה מקבל את השגיאה הבאה

Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
at javax.crypto.Cipher.implInit(Cipher.java:786)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1213)
at javax.crypto.Cipher.init(Cipher.java:1153)
at testCipher.Driver.main(Driver.java:34)

אם הודפס לך מעל השגיאה 128ביט -> אתה לא יכול להשתמש עם מפתחות גדולים מ16bytes במקרה לפי הבנתי המפתח שלך הוא 32bytes
לא יודע מה הרציונל מאחורי זה, אתה יכול לקרוא על זה באינטרנט אם בא לך...
 

קונדסבא

New member
צ'מע קודם כל תודה רבה על העזרה


דבר שני, אני דיי גרוע בכל הקטע הזה של הקידודים....אז כמה דברים:
קודם כל אתה קיבלתי ג'בריש בגלל שזה לא קידוד ישיר...אחרי שאני מקבל את הפלט של encrypt אני צריך לעשות עוד כמה xor בשביל לקבל את ההודעה.
דבר שני, נחזור לקטע עם הקידודים שאני גרוע בו. לפי מה שאני הבנתי, בגלל שהסטרינג אמור להיות מקודד לHex אז המפתח שלי הוא בעצם רק 16 בתים לא? (ולא 32)...
דבר שלישי...איזה קידוד אני צריך להכניס לcharset כשאני עושה getbytes לסטרניג? אם אני עושה פשוט s.getBytes() zz זה לא עובד לי....אני מקבל ג'יבריש.
 

nocgod

New member
ואללה לא יודע

פרסם את כל השאלה במלואה, אני לא יכול לנחש דברים...פרסם את כל תנאי התרגיל וכל הinput שלו ומה מצפים ממני לקבל בoutput
 

קונדסבא

New member
באסה

אין לי בעיה לפרסם פה את השאלה אבל זה באמת חסר טעם...זה גם לרדת לפרטים טכניים בשרשרת ההצפנה שדווקא איתם הסתדרתי טוב.
בעיקרון זאת השאלה:

While we ask that you implement both encryption and decryption, we will only test the decryption function. In the following questions you are given an AES key and a ciphertext (both are hex encoded) and your goal is to recover the plaintext and enter it in the input boxes provided below.

For an implementation of AES you may use an existing crypto library such as PyCrypto (Python), Crypto++ (C++), or any other. While it is fine to use the built-in AES functions, we ask that as a learning experience you implement CBC and CTR modes yourself.

Question 1
CBC key: 140b41b22a29beb4061bda66b6747e14
CBC Ciphertext 1:
4ca00ff4c898d61e1edbf1800618fb2828a226d160dad07883d04e008a7897ee\
2e4b7465d5290d0c0e6c6822236e1daafb94ffe0c5da05d9476be028ad7c1d81


כמו שאמרתי, השאלה עצמה זה לא הבעיה...והכל עובד לי יופי חוץ מהבלוק האחרון...לא יודע אם למדת על aes אבל אם לא, אז בעיקרון זה לוקח את ההודעה מפרק אותה לבלוקים בגודל 16 bytes וכל בלוק מפוענח בנפרד,סוג של... קיצר יש לי לולאת for שמכניסה בלוק למחלקה cipher (כמו שכתבתי למעלה) ומוציאה טקסט מפוענח. שני בלוקים עוברים לי חלק, אבל משום מה הבלוק השלישי זורק את האקספשן. מה שראית למעלה זה בניסיון שלי לדבג לקחתי בצורה ידנית את 16 bytes האחרונים וניסיתי להזין לcipher וכמו שראית זה עדיין זרק את האקספשן. אם אני אצליח לגלות למה הוא חושב שהבלוק האחרון הוא לא מגודל 16 סיימתי את התרגיל.
בכל מקרה עזרת לי כבר מעל ומעבר...אם במקרה נופל לך האסימון (או למישהו שקורא את ההודעה הזאת) אני אשמח לעזרה, אם לא אז לא נורא...אני כבר אמשיך הלאה.
 

קונדסבא

New member
אוקיי... פריצת דרך מדעית

byte test[]= new BigInteger("fb94ffe0c5da05d9476be028ad7c1d81",16).toByteArray();
byte test2[]= new BigInteger("4ca00ff4c898d61e1edbf1800618fb28",16).toByteArray();



הגודל של test הוא באמת 17(!) לעומת test2 שהגדול שלו הוא 16 כמו שציפיתי. למה זה קורה?
 

nocgod

New member
הראש שלי לא חושב כבר...זה הניסיון הכי קרוב...

public static void main(String args[])
{
String key = "140b41b22a29beb4061bda66b6747e14";
String encrypt = "fb94ffe0c5da05d9476be028ad7c1d81";
String decrypted = decrypt(key, encrypt);
System.out.println("decrypted string: " + decrypted);
System.out.println("decrypted hex: " + new BigInteger(decrypted.getBytes()).toString(16));
}

public static String decrypt(String key, String encrypted)
{
try
{
Key k = new SecretKeySpec(key.getBytes(), "AES");
Cipher c = Cipher.getInstance("AES/CBC/NoPadding");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
c.init(Cipher.DECRYPT_MODE, k, ivspec);
byte[] decodedValue = encrypted.getBytes();
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
catch (Exception e)
{
e.printStackTrace();
}

return null;
}
}
 

קונדסבא

New member
גם אני בדיוק הצלחתי לפתור את זה

בדרך ממש עקמה...הוספתי if שבודק אם ה[]byte המתקבל הוא בגודל 17, ואם כן אז תיצור byte[] חדש ותוריד את הביט הכי שמאלי.
לא כל כך הבנתי מה הסיפור אבל מקריאה בגוגל ראיתי שלפעמים כשממירים BigInteger מתווסף עוד ביט אחד עם ערך 0 והוא מייצג את הסימן(?).
מכיוון שהסימן לא מעניין אותי (ככל הנראה) פשוט הורדתי אותי.
בעיקרון סיימתי את התרגיל. אבל סתם מתוך סקרנות (וגם אולי זה יצוץ לי בתרגילים הבאים), יש דרך קצת פחות ברוטלית להמיר BigInteger למערך של בייטים בלי סימן??
 

קונדסבא

New member
דרך אגב בשיטה שלך

להשתמש בgetBytes זה כנראה באמת משמיט את הסימן, אבל זה יצר לי בעיות אחרות שאין לי מושג מה המקור שלהם...
 

BravoMan

Active member
התשובה מאוד פשוטה, והיא נמצאת

במשפט השני של התיעוד באתר של Oracle:

All operations behave as if BigIntegers were represented in two's-complement notation


המחלקה הזו מייצגת מספרים בשיטת המשלים ל-2, לכן, כל מספר שתכניס עליה יצטרך מספיק מקום לייצוג כזה.

בלי הבית הנוסף, מספר ש-4 הביטים המובילים שלו הם f כמו בדוגמה שלך, יתפרש כמספר שלילי, לכן כש-BigInt מפרש את מחרוזת ה-Hex שסיפקת לו (שהוא בטוח שהיא חיובית) הוא דואג לייצוג הנכון שלה שדורש עוד בית (הוא לא יכול להקצות פחות, גם אם ביט אחד היה מספיק).

כמו שכתבתי לך קודם: ב-Java אין טיפוסים unsigned כמו שקיימים ב-C או ++C, והדרך היחידה לוודא שמספרים בטווח מסוים יתפרשו תמיד כחיוביים לצורך פעולות חשבוניות או פורמט הדפסה היא לעבוד עם טיפוס שהוא גדול לפחות בבית אחד מהגודל המקסימלי של המספרים איתם עובדים.
 

קונדסבא

New member
תמיד היה לי קושי להבין את הקידודים האלה

קראתי מה שכתבת, וזה שלח אותי גם לקרוא בויקיפדיה על שיטת המשלים ל-2 ואני מצליח פחות או יותר להבין את ההיגיון בהכנסת הביט הנוסף אבל לא באמת מצליח להבין לעומק את הדברים. מעניין אם יום יבוא וזה יחלחל....
 
למעלה