PDA

View Full Version : XML Encryption در جاوا



pesare
چهارشنبه 09 مهر 1393, 13:59 عصر
سلام دوستان

در جاوا چطوری میشه Elenment های یه فایل XML رو Encrypt کرد؟

ahmad.mo74
چهارشنبه 09 مهر 1393, 15:11 عصر
سلام، من نمیدونم کل xml رو میشه encrypt کرد یا نه ولی میتونید المنتهایی که مدنظر دارید رو با AES یا هر جور دلخواه دیگه انکریپت کنید، ضمنا برای اینکه از تغییر دادن محتویاتش توسط کاربر جلوگیری کنید hash مربوط به فایل xml رو تو فایل جداگانه دیگه ای قرار بدید تا با مقایسه کردنش معلوم بشه تغییر داده یا نه و در اونصورت بهش اخطار بدید یا هر چیز دیگه...

مثلا:

کلاس Account :


import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


/**
* @author avb
*/
@XmlRootElement
public class Account {


private long id;
private String name;
private String email;
private String password;


public Account() {
}


public Account(long id, String name, String email, String password) {
this.id = id;
this.name = name;
this.email = email;
this.password = password;
}


public long getId() {
return id;
}


@XmlAttribute
public void setId(long id) {
this.id = id;
}


public String getName() {
return name;
}


@XmlElement
public void setName(String name) {
this.name = name;
}


public String getEmail() {
return email;
}


@XmlElement
public void setEmail(String email) {
this.email = email;
}


public String getPassword() {
return password;
}


@XmlElement
public void setPassword(String password) {
this.password = password;
}


}


AESEncryption :


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;


public class AESEncryption {


private final static String HEX = "0123456789ABCDEF";


public static String doEncrypt(String clearText, String key) {
try {
return encrypt(key, clearText);
} catch (Exception e) {
return "";
}
}


public static String doDecrypt(String encrypted, String key) {
try {
return decrypt(key, encrypted);
} catch (Exception e) {
return "";
}
}


private static String encrypt(String seed, String clearText) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, clearText.getBytes());
return toHex(result);
}


private static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}


private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
keyGenerator.init(128, sr);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}


private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(clear);
}


private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
return cipher.doFinal(encrypted);
}


private static byte[] toByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
return result;
}


private static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2 * buf.length);
for (byte aBuf : buf) {
appendHex(result, aBuf);
}
return result.toString();
}


private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}


}


ObjectMarshaller :


import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
* @author avb
*/
public class ObjectMarshaller {


private static final String HEX = "0123456789ABCDEF";


public <T> boolean toXml(T object, String path) {
try {
File file = new File(path);
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
Marshaller jaxbAMarshaller = jaxbContext.createMarshaller();
jaxbAMarshaller.setProperty(Marshaller.JAXB_FORMAT TED_OUTPUT, true);
jaxbAMarshaller.marshal(object, file);
byte[] checkSum = createCheckSum(file);
return saveCheckSum(checkSum, path);
} catch (JAXBException | IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
return false;
}


private byte[] createCheckSum(File file) throws IOException, NoSuchAlgorithmException {
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
sha1.update(buffer, 0, numRead);
}
} while (numRead != -1);
}
return sha1.digest();
}


private boolean saveCheckSum(byte[] checkSum, String fileName) throws IOException {
try (FileOutputStream fos = new FileOutputStream(fileName + ".chk")) {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))) {
writer.write(getHex(checkSum));
writer.flush();
}
fos.flush();
}
return true;
}


private String getHex(byte[] raw) {
if (raw == null) {
return null;
}
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEX.charAt((b & 0xF0) >> 4)).append(HEX.charAt((b & 0x0F)));
}
return String.valueOf(hex);
}


}


ObjectUnmarshaller :


import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
* @author avb
*/
public class ObjectUnmarshaller {


private static final String HEX = "0123456789ABCDEF";


@SuppressWarnings("unchecked")
public <T> T toObject(T object, String path) {
if (Files.exists(Paths.get(path))) {
try {
File file = new File(path);
byte[] checkSum = getCheckSum(file);
if (!getHex(checkSum).equals(getCheckSum(path))) {
System.out.println("this file has been modified!");
return null;
}
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return (T) jaxbUnmarshaller.unmarshal(file);
} catch (JAXBException | NoSuchAlgorithmException | IOException e) {
System.out.println("Oops, cannot load xml file!");
e.printStackTrace();
}
}
return null;
}


private byte[] getCheckSum(File file) throws IOException, NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA1");
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[1024];
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
digest.update(buffer, 0, numRead);
}
} while (numRead != -1);
}
return digest.digest();
}


private String getCheckSum(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path + ".chk")) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
return reader.readLine();
}
}
}


private String getHex(byte[] raw) {
if (raw == null) {
return null;
}
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEX.charAt((b & 0xF0) >> 4)).append(HEX.charAt((b & 0x0F)));
}
return String.valueOf(hex);
}


}


Test :


/**
* @author avb
*/
public class Test {


private static final String KEY = "abc123";


public static void main(String[] args) {
long id = 123213;
String name = encrypt("ahmad");
String email = encrypt("ahmad@gmail.com");
String password = encrypt("Ahmad1234");
Account account = new Account(id, name, email, password);
ObjectMarshaller marshaller = new ObjectMarshaller();
System.out.println(marshaller.toXml(account, "C:\\users\\myuser\\desktop\\account.xml"));
ObjectUnmarshaller unmarshaller = new ObjectUnmarshaller();
Account retrieve = new Account();
retrieve = unmarshaller.toObject(retrieve, "C:\\users\\myuser\\desktop\\account.xml");
System.out.println(retrieve.getId());
System.out.println(decrypt(retrieve.getName()));
System.out.println(decrypt(retrieve.getEmail()));
System.out.println(decrypt(retrieve.getPassword()) );
}


public static String encrypt(String clearText) {
return AESEncryption.doEncrypt(clearText, KEY);
}


public static String decrypt(String encrypted) {
return AESEncryption.doDecrypt(encrypted, KEY);
}


}


Output:

account.xml :


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<account id="123213">
<email>6BF897FD72C45D7510A26D965E556799</email>
<name>301BDF96016EF4E5D7C5804FC2DA8108</name>
<password>70837DA6B8721033B0A5EFFEE9248B43</password>
</account>


account.xml.chk :



C89F3BA6FF54125679A1884A2CE670F40835F2FA

pesare
چهارشنبه 09 مهر 1393, 15:21 عصر
اگه یه توضیح کوچیک در باره روند کار و متدها بدید هم بدید ممنون میشم

ahmad.mo74
چهارشنبه 09 مهر 1393, 15:23 عصر
در کدوم مورد؟ همش؟؟؟

pesare
چهارشنبه 09 مهر 1393, 15:28 عصر
اگه سختتون نیست همش

ahmad.mo74
چهارشنبه 09 مهر 1393, 15:52 عصر
:))

اول درباره کلاس Account و annotation هایی که توش استفاده شده :

http://www.techferry.com/articles/jaxb-annotations.html
http://docs.oracle.com/javaee/5/api/javax/xml/bind/annotation/package-summary.html

دوم درباره AES :

http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
http://aesencryption.net/
http://searchsecurity.techtarget.com/definition/Advanced-Encryption-Standard

بازم سرچ کنید انواع و اقسام الگوریتم های دیگه برای AES رو پیدا میکنید، البته من خودم یه خورده تغییرات دادم توش

اما درباره کلاس های ObjectMarshaller و ObjectUnmarshaller :

تو جاوا راههای مختلفی برای کار با xml فراهم شده :

http://stackoverflow.com/questions/373833/best-xml-parser-for-java
http://en.wikipedia.org/wiki/Java_API_for_XML_Processing

حالا ما اینجا از JAXB استفاده کردیم...

خیلی راحت یه آبجکت بهش میدیم و اون هم بر اساس annotation هایی که براش تعیین کردیم xml بهمون تحویل میده و برعکس، یعنی xml و نوع کلاس رو بهش میدیم تا بر اساس اون کلاس xml رو تجزیه و تحلیل بکنه و آبجکتش رو بهمون برگردونه...

اما اینکه hash و checksum و ... چیه؟ http://en.wikipedia.org/wiki/Checksum

ما اینجا اومدیم checksum فایل xml ای که ساختیم (یا هر فایل دیگه ای) رو توی فایل دیگه ای ذخیره کردیم...خب به چه درد میخوره؟

هر فایلی با توجه به محتویات و تک تک بایت هاش checksum مخصوص خودش رو داره و فقط و فقط هم مختص خودشه (البته اگر از sha1 استفاده بشه میشه گفت قطعا همینطوریه چون md5 ضعیف تره و ممکنه بشه معادلش رو ایجاد کرد)
ما هم برای اینکه موقع لود کردن فایلمون مطمئن بشیم که دقیقا همونیه که ما قبلا ساختیم اومدیم دوباره checksum رو محاسبه کردیم و با اونی که قبلا ذخیره کردیم مقایسه کردیم... اگر یکسان بود یعنی دقیقا همونه ولی اگر نبود یعنی دستکاری شده؛ مثلا اگر حتی یک حرف تو فایل xml ای که ساختیم عوض بشه پیغام میده که فایل دستکاری شده!