오늘은.. 어제 IOS 에 이어서.. Android RSA 암호화를 작성해봅니다.
우선 이쪽에서는.. 작업은 수월했지만 두가지 이슈가 잇엇는데요
이슈 1. 세션 유지 (웹 호출을 하는데 세션이 유지되질 않아서 개인키를 찾질 못하는 상황 발생)
이슈 2. 암호화 padding 값에 의한 복호화 오류
우선 작업 배경은.. IOS 때와 마찬가지로 아래와 같습니다.
1. 공개키를 서버에 요청하면, 서버에서는 공개키를 반환함과 동시에 세션을 만들어 개인키를 저장합니다.
2. Android는 공개키에 대한 Modulus 와 Exponent 값을 16진수형태로 수신받는다.
3. 수신받은 값을 토대로 PublicKey 를 생성
4. 암호화 결과로 나온 byte array 를 16진수 화 시켜서 로그인시 사용
>>> 여기서 문제 발생. 세션에 저장한 개인키를 찾지 못함.
이슈 1에 대한 문제 해결
// HttpClient 를 매번 새로 만들지 않고 한번 만든 상태로 반복 사용을 하면 세션이 유지된다고 함.
static HttpClient httpClient = new DefaultHttpClient();
public static String getHttpDataString_forLogin(String URL){
// 로그인 과정의경우
// 1. 암호화를 위해 퍼블릭키를 서버에 요청
// 2. 서버는 퍼블릭키는 반환하면서 동시에 세션에 개인키를 저장
// 3. 암호화한 비밀번호로 로그인 요청 시 서버에서 유지된 세션에서 개인키를 꺼내서 복호화 진행
// HttpClient 을 매번 생성하면 세션유지가 되지 않으므로.. 로그인 관련 호출만 별도로 관리!
Log.i("http_forLogin call", URL);
try {
URI url = new URI(URL);
HttpPost httpPost = new HttpPost();
httpPost.setURI(url);
HttpResponse response = httpClient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
return responseString;
} catch (Exception e){
e.printStackTrace();
}
return null;
}
암호화 소스
try{
Log.i("RSA", "퍼블릭키 요청");
// 암호화에 사용할 Public Key 수신
JSONObject jo = SHPro.getPublicKey();
String publicKeyModulus = jo.getString("publicKeyModulus");
String publicKeyExponent = jo.getString("publicKeyExponent");
Log.i("RSA", "퍼블릭키 수신 완료");
// 암호화 환경 구성
Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
BigInteger modulus = new BigInteger(publicKeyModulus, 16);
BigInteger exponent = new BigInteger(publicKeyExponent, 16);
RSAPublicKeySpec pubks = new RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(pubks);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
Log.i("RSA", "암호화 준비 완료");
// 암호화 Start
byte[] pwdBytes = pwd.getBytes();
byte[] encByte = cipher.doFinal(pwdBytes);
pwd = bytesToHex(encByte);
Log.i("RSA", "암호화 성공 : " + pwd);
// 암호화 End
}catch(Exception e){
Log.e("RSA","암호화 실패 : " + e.toString());
return;
}
암호화 소스에서 참조하는 16진수화 함수
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
이슈 2
Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding");
여기서.. 일반적으로 구글링을 했을 때 나오는 "RSA/NONE/NoPadding"을 해봤으나.. 계속 서버에서 복호화를 하면서 패딩오류가 나는것..
이곳저곳 찾아보니 아래 URL 로 접근해본 결과 종류별로 padding 이 정리되어있길래 나한태 적합한 옵션을 찾을 수 있었다.
http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html
댓글
댓글 쓰기