새소식

반응형
Java/Spring

RSA 암호화 만들기

  • -
반응형

RSA 암호화

공개키 암호시스템 중 한개, 암호화 뿐만 아니라 전자서명도 가능한 최초의 알고리즘으로 알려진다.

RSA는 두개의 키를 사용한다. 공개키개인키를 사용하는데 공개키평문을 암호화 하는데 사용하고

개인키암호화한 데이터를 복호화할때 사용한다. 이를 비대칭키라고 하며 누구나 어떤 메시지를 암호화 할수 있지만

암호화한 데이터는 개인키를 가지고 있는 사람만 복호화 할 수 있다.

 

일반적으로 공개키는 n 과 e 값으로 구성되어 있습니다.

n 값은 Modulus 이며 e 값은 Public exponent 값입니다.

 

개인키는 기본적으로 n, e, d, p, q, exponent1, exponent2, coefficient 값을 갖습니다. 여기서 가장 필요한 값은 d 입니다.

개인키의 각 값은 공개키의 데이터 값을 포함합니다.

 

여기서는 암호화만 진행할 예정이다.

 

RsaUtils.java

package com.angular.web.utils;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import org.springframework.stereotype.Component;

import com.angular.web.utils.Funcs;

@Component
public class RsaUtils {
    //공개키
    private PublicKey publicKey;
    //개인키
    private PrivateKey privateKey;

    //공개키 및 개인키의 N 값
    private String publicKeyModulus;
    //공개키 및 개인키의 E 값
    private String publicKeyExponent;

    KeyPairGenerator gen;

public RsaUtils() {
    try {
        //1024 RSA 키쌍을 생성
        gen = KeyPairGenerator.getInstance("RSA");
        gen.initialize(1024);
        KeyPair keys = gen.genKeyPair();
        publicKey = keys.getPublic();
        privateKey = keys.getPrivate();

        //만들어진 공개키의 N(Modulus) 값과 E(Exponent)값을 문자열로 가져온다.
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec publicSpec = keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);

        publicKeyModulus = publicSpec.getModulus().toString(16);
        publicKeyExponent = publicSpec.getPublicExponent().toString(16);

    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
        publicKey = null;
        privateKey = null;

        publicKeyModulus = null;
        publicKeyExponent = null;
    }

}

public PublicKey getPublicKey() {
    return publicKey;
}

public void setPublicKey(PublicKey publicKey) {
    this.publicKey = publicKey;
}

public PrivateKey getPrivateKey() {
return privateKey;
}

public void setPrivateKey(PrivateKey privateKey) {
    this.privateKey = privateKey;
}

public String getPublicKeyModulus() {
    return publicKeyModulus;
}

public void setPublicKeyModulus(String publicKeyModulus) {
    this.publicKeyModulus = publicKeyModulus;
}

public String getPublicKeyExponent() {
    return publicKeyExponent;
}

public void setPublicKeyExponent(String publicKeyExponent) {
    this.publicKeyExponent = publicKeyExponent;
}

public KeyPairGenerator getGen() {
    return gen;
}

public void setGen(KeyPairGenerator gen) {
    this.gen = gen;
}
//암호화
public String decrypt(String secureInfo) {
    String secureDecryptInfo = "";
    try{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        /**
        * 암호화 된 값은 byte 배열이다.
        * 이를 문자열 폼으로 전송하기 위해 16진 문자열(hex)로 변경한다.
        * 16진 문자열로 변경하기 위해 funcs이라는 utils 이용
        * 서버에서도 값을 받을 때 hex 문자열을 받아서 다시 byte 배열로 바꾼 뒤에 복호화 과정을 수행한다.
        * 아래의 Funcs는 16진수 변환을 위한 utils 파일, 아래에서 첨부할꺼다
        */
        byte[] encryptedBytes = Funcs.hexToByteArray(secureInfo);
        if( encryptedBytes == null) return null;
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        secureDecryptInfo = new String(decryptedBytes, "utf-8"); // 문자 인코딩 주의.
        return secureDecryptInfo;
    }catch(Exception e)
    {
        return null;
    }

}

}

 

Funcs.java 에서 사용할 pom.xml에 dependency 추가

 

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

 

Funcs.java

Funcs.java
0.01MB

package com.angular.web.utils;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Funcs {

private static final char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'd', 'd', 'e', 'f' };

public static String getkey(HashMap<String, String> m, String v){
for(String o: m.keySet())
{
if(m.get(o).equals(v))
{
return o;
}
}
return null;

}
public static String encodingURL(String url){
try {
return URLEncoder.encode(url, "UTF-8").replaceAll("\\+", "%20");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
//에러시 주요 문자만 인코딩
return url.replaceAll(" ", "%20").replaceAll("//", "%2F").replaceAll("+", "%2B");
}
}
public static String getMD5Str(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bf = md.digest(input.getBytes("UTF-8"));
StringBuilder stbf = new StringBuilder();
for( int i = 0; i < bf.length ; i++) {
stbf.append(HEXCHAR[((bf[i]>>4) & 0x0f)]);
stbf.append(HEXCHAR[(bf[i] & 0x0f)]);
}
return stbf.toString();
} catch (NoSuchAlgorithmException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}

public static String getSha512Str( String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] bf = md.digest(input.getBytes());
StringBuilder stbf = new StringBuilder();
for( int i = 0; i < bf.length ; i++) {
stbf.append(HEXCHAR[((bf[i]>>4) & 0x0f)]);
stbf.append(HEXCHAR[(bf[i] & 0x0f)]);
}
return stbf.toString();
} catch (NoSuchAlgorithmException e) {
}
return null;
}

public static byte[] hexToByteArray(String input) {
if (input == null || input.length() % 2 != 0) {
return null;
}
byte[] bytes = new byte[input.length() >> 1];
for (int i = 0; i < input.length(); i += 2) {
byte value = (byte)Integer.parseInt(input.substring(i, i + 2), 16);
bytes[(i>>1)] = value;
}
return bytes;
}

public static final void convtCommaStr( String str , List<String> lststr) {
if( str == null || str.length() == 0) return;

char[] buf = str.toCharArray();
int pt, spt, cnt, stat,len;
pt = spt = cnt = 0;
len = buf.length;
char nextfind;

try {
while( pt < len) {
if( buf[pt] == '"') {
nextfind = '"';
stat = 2;
pt++;
spt = pt;
} else {
if( buf[pt] == ',') {
lststr.add("");
pt++;
if( pt == len) {
lststr.add("");
}
spt = pt;
continue;
} else {
nextfind = ',';
stat = 1;
spt = pt;
cnt++;
pt++;
}
}
while (pt < len ) {
if( buf[pt] != nextfind) {
pt++; cnt++; continue;
}
if( stat == 1) {
lststr.add( new String(buf, spt, cnt));
pt++;
if(pt == len) {
lststr.add("");
}
cnt = 0;
break;
}
if(stat == 2) {
pt++;
if( buf[pt] != nextfind) {
lststr.add( new String(buf, spt, cnt));
cnt = 0;
pt++;
if( pt == len) {
lststr.add("");
}
break;
} else {
int i = pt;
while( i < len) {
buf[i-1] = buf[i];
i++;
}
len--;
cnt++;
}
}
}
}
if( cnt > 0)
lststr.add( new String( buf, spt, cnt));
}
catch( Exception e) {
if( cnt > 0)
lststr.add( new String(buf, spt, cnt));
}
}

public static final List<String> convtCommaStr( String str ) {
if( str == null || str.length() == 0) return null;

char[] buf = str.toCharArray();
int pt, spt, cnt, stat,len;
pt = spt = cnt = 0;
len = buf.length;
char nextfind;
List<String> lststr = new ArrayList<String>();

try {
while( pt < len) {
if( buf[pt] == '"') {
nextfind = '"';
stat = 2;
pt++;
spt = pt;
} else {
if( buf[pt] == ',') {
lststr.add("");
pt++;
if( pt == len) {
lststr.add("");
}
spt = pt;
continue;
} else {
nextfind = ',';
stat = 1;
spt = pt;
cnt++;
pt++;
}
}
while (pt < len ) {
if( buf[pt] != nextfind) {
pt++; cnt++; continue;
}
if( stat == 1) {
lststr.add( new String(buf, spt, cnt));
pt++;
if(pt == len) {
lststr.add("");
}
cnt = 0;
break;
}
if(stat == 2) {
pt++;
if( buf[pt] != nextfind) {
lststr.add( new String(buf, spt, cnt));
cnt = 0;
pt++;
if( pt == len) {
lststr.add("");
}
break;
} else {
int i = pt;
while( i < len) {
buf[i-1] = buf[i];
i++;
}
len--;
cnt++;
}
}
}
}
if( cnt > 0)
lststr.add( new String( buf, spt, cnt));
}
catch( Exception e) {
if( cnt > 0)
lststr.add( new String(buf, spt, cnt));
}
return lststr;
}

public static final String[] commaStrToStrs( String str , int count) {
if( str == null || str.length() == 0) return null;

String[] arstrs = new String[count];
int numidx = 0;
char[] buf = str.toCharArray();
int pt, spt, cnt, stat,len;
pt = spt = cnt = 0;
len = buf.length;
char nextfind;

try {
while( pt < len) {
if( buf[pt] == '"') {
nextfind = '"';
stat = 2;
pt++;
spt = pt;
} else {
if( buf[pt] == ',') {
if( numidx == count) return null;
arstrs[numidx] = "";
numidx++;
pt++;
if( pt == len) {
if( numidx == count) return null;
arstrs[numidx] = "";
numidx++;
}
spt = pt;
continue;
} else {
nextfind = ',';
stat = 1;
spt = pt;
cnt++;
pt++;
}
}
while (pt < len ) {
if( buf[pt] != nextfind) {
pt++; cnt++; continue;
}
if( stat == 1) {
if( numidx == count) return null;
arstrs[numidx] = new String(buf, spt, cnt);
numidx++;
pt++;
if(pt == len) {
if( numidx == count) return null;
arstrs[numidx] = "";
numidx++;
}
cnt = 0;
break;
}
if(stat == 2) {
pt++;
if( buf[pt] != nextfind) {
if( numidx == count) return null;
arstrs[numidx] = new String(buf, spt, cnt);
numidx++;
pt++;
if( pt == len) {
if( numidx == count) return null;
arstrs[numidx] = "";
numidx++;
}
cnt = 0;
break;
} else {
int i = pt;
while( i < len) {
buf[i-1] = buf[i];
i++;
}
len--;
cnt++;
}
}
}
}
if( cnt > 0) {
if( numidx == count) return null;
arstrs[numidx] = new String( buf, spt, cnt);
numidx++;
}
}
catch( Exception e) {
if( cnt > 0) {
if( numidx == count) return null;
arstrs[numidx] = new String( buf, spt, cnt);
numidx++;
}
}
if( count == numidx ) return arstrs;
else return null;
}

public static Map ConverObjectToMap(Object obj){
try {
//Field[] fields = obj.getClass().getFields(); //private field는 나오지 않음.
Field[] fields = obj.getClass().getDeclaredFields();
Map resultMap = new HashMap();
for(int i=0; i<=fields.length-1;i++){
fields[i].setAccessible(true);
resultMap.put(fields[i].getName(), fields[i].get(obj));
}
return resultMap;
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}


public static String toJson(Object obj){
ObjectMapper mapper = new ObjectMapper();
String json = "";

try {
json = mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return json;
}

public static CloseableHttpClient createAcceptSelfSignedCertificateClient()
throws Exception {

SSLContext sslContext = SSLContextBuilder
.create()
.loadTrustMaterial(new TrustSelfSignedStrategy())
.build();

sslContext.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
HostnameVerifier allowAllHosts = new HostnameVerifier(){
public boolean verify(String hostname, SSLSession session) {
return true;
}
};

SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

return HttpClients
.custom()
.setSSLSocketFactory(connectionFactory)
.build();
}
private static class DefaultTrustManager implements X509TrustManager {

@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}

}
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.