상세 컨텐츠

본문 제목

보안 PKI 예제 (Security PKI example)

보안

by MustThanks 2020. 8. 9. 19:09

본문

반응형

package small.bit.coin.custom;

 

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.math.BigInteger;

import java.security.InvalidKeyException;

import java.security.Key;

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.SecureRandom;

import java.security.Security;

import java.security.Signature;

import java.security.SignatureException;

import java.security.spec.ECGenParameterSpec;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

 

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.util.encoders.Base64;

 

import small.bit.coin.util.PemFileObject;

 

 

public class EccInstanceObject {

 

 

public static void main(String [] args)

{

 

 // 바운시 캐슬의 암호화 라이브러리를 사용하도록 설정.

Security.addProvider(new BouncyCastleProvider());

 

// 타원 곡선 객체를 생성해 개인키와 공개키를 각각 private.pem, public.pem으로 저장.

EccInstanceObject eccObject = new EccInstanceObject("private.pem", "public.pem");

 

//eccObject.callOne(eccObject);

 

 

try {

eccObject.callTwo(eccObject);

} catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | SignatureException

| IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

 

 

}

 

public void  callOne(EccInstanceObject eccObject)

{

 

try {

eccObject.generate();

} catch (Exception e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

 

// 파일로 저장한 개인키와 공개키를 다시 프로그램으로 불러옵니다.

    try {

PrivateKey privateKey = eccObject.readPrivateKeyFromPemFile("private.pem");

} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

    try {

PublicKey publicKey = eccObject.readPublicKeyFromPemFile("public.pem");

} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

 

String strPrivateFileName;

String strPublicFileName;

 

 

public EccInstanceObject(String pPrivateKeyFileName, String pPublicKeyFileName)

{

strPrivateFileName = pPrivateKeyFileName;

strPublicFileName  = pPublicKeyFileName;

 

//  바운시 캐슬의 암호화 라이브러리를 사용하도록 설정.

Security.addProvider(new BouncyCastleProvider());

}

 

public void callTwo(EccInstanceObject eccObject) throws FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, InvalidKeyException, SignatureException

{

 

try {

//두 쌍의 키를 생성해 파일 형태로 저장

eccObject.generate("private1.pem", "public1.pem");

eccObject.generate("private2.pem", "public2.pem");

} catch (Exception e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

 

 

// 파일로 저장한 개인키와 공개키를 다시 프로그램으로 불러옵니다.

PrivateKey privateKey1=null;

PublicKey publicKey1=null;

    privateKey1 = eccObject.readPrivateKeyFromPemFile("private1.pem");

publicKey1  = eccObject.readPublicKeyFromPemFile("public1.pem");

 

 

    PrivateKey privateKey2=null;

     PublicKey publicKey2=null;

     privateKey2 = eccObject.readPrivateKeyFromPemFile("private2.pem");

     publicKey2  = eccObject.readPublicKeyFromPemFile("public2.pem");

 

     Signature signature=null;

    String strAlgorithm = "SHA1withECDSA";

   

    signature = Signature.getInstance(strAlgorithm);

 

    // 개인키 1을 이용해 암호화(서명)합니다.

    signature.initSign(privateKey1);

   

    

    String strChar = "UTF-8";

    String text = "평문입니다.";

  

    System.out.println("평문 정보: " + text);

    byte[]  byteText = text.getBytes(strChar);

  

    // 평문 데이터를 암호화하여 서명한 데이터를 출력합니다.

    signature.update(byteText);

    byte[] byteSignature = signature.sign();

    System.out.println("서명된 값: 0x" + (new BigInteger(1, byteSignature).toString(16)).toUpperCase());

 

    

    Signature signatureTwo;

    signatureTwo = Signature.getInstance(strAlgorithm);

    

 

    // 검증할 때는 공개키 2를 이용해 복호화를 수행합니다.

   // signatureTwo.initVerify(publicKey1); //true

    signatureTwo.initVerify(publicKey2);   //false

    signatureTwo.update(byteText);

    boolean result = signatureTwo.verify(byteSignature);

 

    // 개인키와 매칭되는 공개키가 아니므로 복호화에 실패합니다.

    System.out.println("신원 검증: " + result);

 

    

}

 

//세부 알고리즘으로 sect163k1을 이용

private final String STR_ARGORITHM = "sect163k1";

 

//바운시 캐슬의 타원 곡션 표준 알고리즘(ECDSA)를 사용

private final String STR_STD_ARGORLTHM = "ECDSA";

//알고리즘 공금자정보

private final String STR_STD_PROVIDER = "BC";

 

//PK에 대한 설명

private final String STR_PRIVATE_DESC = "EC PRIVATE KEY";

//공개키에 대한 설명

private final String STR_PUBLIC_DESC = "EC PUBLIC KEY";

 

//private 시작을 알리는 내용

private final String STR_PRIVATE_BEGIN  = "-----BEGIN EC PRIVATE KEY-----";

//private 종료를 알리는 내용

private final String STR_PRIVATE_END  = "-----END EC PRIVATE KEY-----";

 

//public 시작을 알리는 내용

private final String STR_PUBLIC_BEGIN  = "-----BEGIN EC PUBLIC KEY-----";

//public 종료를 알리는 내용

private final String STR_PUBLIC_END  = "-----END EC PUBLIC KEY-----";

 

private final String STR_EMPTY = "";

 

 

//개인키와 공개키를 생성하기위한 Object

KeyPairGenerator  generator;

 

//타원 곡선의 알고리즘 생성 Object

ECGenParameterSpec  eCGenParameterSpec;

 

//키쌍을 생성

KeyPair keyPair;

 

//개인키(비밀키)

PrivateKey  privateKey;

 

//공개키

PublicKey  publicKey;

 

private String sPrivateKeyName="";

private String sPublicKeyName="";

 

//개이키와 공개키를 생성하여 파일에 저장하는 기능

public void generate () throws Exception

{

generate (strPrivateFileName, strPublicFileName);

}

 

 

//개이키와 공개키를 생성하여 파일에 저장하는 기능

public void generate (String pPrivateKeyName, String pPublicKeyName) throws Exception

{

//바운시 캐슬의 타원 곡션 표준 알고리즘(ECDSA)를 사용

generator = KeyPairGenerator.getInstance(STR_STD_ARGORLTHM, STR_STD_PROVIDER);

 

//타원 곡선의 세부 알고리즈으로 sect163k1을 사용

eCGenParameterSpec = new ECGenParameterSpec(STR_ARGORITHM);

 

//키생성을 위한 알고리즘과 인자 초기화

generator.initialize(eCGenParameterSpec, new SecureRandom());

 

//해당 알고리즘으로 무작위(랜덤)의 키 한 쌍을 생성합니다.

keyPair = generator.generateKeyPair();

System.out.println("암호화 키 한쌍 생성");

 

//공개키와 개인키를 추출

publicKey  = keyPair.getPublic();

privateKey = keyPair.getPrivate();

 

sPrivateKeyName=pPrivateKeyName;

sPublicKeyName =pPublicKeyName;

 

 

// 개인키와 공개키를 특정한 파일 이름으로 저장

writePemFile(  STR_PRIVATE_DESC, privateKey , pPrivateKeyName);

writePemFile(  STR_PUBLIC_DESC , publicKey  , pPublicKeyName);

 

}

 

private String getPrivateKeyName()

{

return sPrivateKeyName;

}

 

 

private String getPublicKeyName()

{

return sPublicKeyName;

}

 

 

// PemFileObject 클래스를 이용해 생성된 암호키를 파일로 저장하는 함수

private void writePemFile(String pDescription, Key pKey, String pFileName) throws FileNotFoundException, IOException

{

 

//PemObject 와 PemWriter를 이용하여 Key를 저장하는 Object

PemFileObject pemFileObject = new PemFileObject(pDescription,pKey);

pemFileObject.write(pFileName);

 

System.out.println(String.format("EC 암호키 %s을(를) %s 파일로 내보냈습니다.", pDescription, pFileName));

}

 

 

public PrivateKey readPrivateKeyFromPemFile(String pPrivateKeyPemFile)

throws FileNotFoundException , IOException, NoSuchAlgorithmException, InvalidKeySpecException

{

 

if(pPrivateKeyPemFile==null  || STR_EMPTY.equals(pPrivateKeyPemFile.trim())) pPrivateKeyPemFile = getPrivateKeyName();

 

String strContext = readStringFromFile(pPrivateKeyPemFile);

 

System.out.println("EC 개인키를 " + pPrivateKeyPemFile + "로부터 불러왔습니다.");

System.out.print(strContext);

 

//파일에 입력되어 있는 설명 구문을 제거

strContext = strContext.replaceAll(STR_PRIVATE_BEGIN,STR_EMPTY);

strContext = strContext.replaceAll(STR_PRIVATE_END,STR_EMPTY);

 

//PEM파일은 Base64로 incoding 되어 있어 decoding 해서 read

byte[] byteDecoded = Base64.decode(strContext);

 

PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(byteDecoded);

KeyFactory keyFactory = KeyFactory.getInstance(STR_STD_ARGORLTHM);

PrivateKey privateKey = keyFactory.generatePrivate(pKCS8EncodedKeySpec);

 

return privateKey;

 

}

 

public PublicKey readPublicKeyFromPemFile(String pPublicKeyPemFile) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException

{

if(pPublicKeyPemFile==null  || STR_EMPTY.equals(pPublicKeyPemFile.trim())) pPublicKeyPemFile = getPublicKeyName();

 

String strContext = readStringFromFile(pPublicKeyPemFile);

 

System.out.println("EC 개인키를 " + pPublicKeyPemFile + "로부터 불러왔습니다.");

System.out.print(strContext);

 

//파일에 입력되어 있는 설명 구문을 제거

strContext = strContext.replaceAll(STR_PUBLIC_BEGIN,STR_EMPTY);

strContext = strContext.replaceAll(STR_PUBLIC_END,STR_EMPTY);

 

//PEM파일은 Base64로 incoding 되어 있어 decoding 해서 read

byte[] byteDecoded = Base64.decode(strContext);

 

X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteDecoded);

KeyFactory keyFactory = KeyFactory.getInstance(STR_STD_ARGORLTHM);

PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

 

return publicKey;

 

}

 

 //문자열을 그대로 읽어오는 함수.

private String readStringFromFile(String pFileName) throws IOException

{

String strContext = "";

 

BufferedReader  bufferReader = new BufferedReader(

                       new FileReader(pFileName));

 

try

{

String str="";

while((str=bufferReader.readLine()) !=null)

{

strContext += str + "\n"; 

}

}

finally

{

bufferReader.close();

}

 

return strContext;

}

 

}

================================================

 

package small.bit.coin.custom;

 

import java.io.FileNotFoundException;

import java.io.IOException;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.Security;

import java.security.Signature;

import java.security.SignatureException;

import java.security.spec.InvalidKeySpecException;

 

import org.bouncycastle.jce.provider.BouncyCastleProvider;

 

public class IntegrityCheckObject {

 

public static void main(String[] args) {

// TODO Auto-generated method stub

 

// 타원 곡선 객체를 생성해 개인키와 공개키를 각각 private.pem, public.pem으로 저장.

EccInstanceObject eccInstanceObject = new EccInstanceObject("private.pem", "public.pem");

 

 

try {

eccInstanceObject.generate();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

IntegrityCheckObject integrityCheckObject = new IntegrityCheckObject(eccInstanceObject);

 

 

 byte[] bytes = integrityCheckObject.getSignaturePrivate("123");

 

 System.out.println(integrityCheckObject.compareIntegrityValue("12",bytes,"public.pem"));  

 

}

 

private EccInstanceObject eccInstanceObject;

 

//개인키

private PrivateKey privateKey;

 

//공개키

private PublicKey  publicKey;

 

private final String STR_EMPTY = "";

 

public IntegrityCheckObject(EccInstanceObject pEccInstanceObject)

{

 // 바운시 캐슬의 암호화 라이브러리를 사용하도록 설정.

Security.addProvider(new BouncyCastleProvider());

 

eccInstanceObject = pEccInstanceObject;

}

 

 

//private key를 가지고 오는 기능

private void getPrivateKey() throws FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException, IOException

{

privateKey = eccInstanceObject.readPrivateKeyFromPemFile(STR_EMPTY);

}

 

//서명을 할 수 있는 기능의 Object

private Signature signaturePrivate = null;

 

//서명에 사용하는 알고리즘

    private final String STR_ALGORITHM  = "SHA1withECDSA";

    

    private final String STR_CHARSET  = "UTF-8";

 

    //private key로 서명한 byte 값을 보관하고 있음

    private byte[] byteSignaturePrivate = null;

 

    //입력값에 private 값을 가지고 서명

private void hasSignaturePrivate(String pPlanText) throws NoSuchAlgorithmException, FileNotFoundException, InvalidKeySpecException, IOException, InvalidKeyException, SignatureException

{

 byte[]  byteText = pPlanText.getBytes(STR_CHARSET);

 

signaturePrivate = Signature.getInstance(STR_ALGORITHM);

getPrivateKey();

 

// 개인키 1을 이용해 암호화(서명)합니다.

signaturePrivate.initSign(privateKey);

 

// 평문 데이터를 암호화하여 서명한 데이터를 출력합니다.

signaturePrivate.update(byteText);

 

byteSignaturePrivate = signaturePrivate.sign();

    

}

 

 

//서명 결과를 반환

public byte[] getSignaturePrivate(String pPlanText)  

{

byte[] reByte=null;

try

{

hasSignaturePrivate(pPlanText);

reByte= byteSignaturePrivate;

}

catch(Exception e)

{

e.printStackTrace();

}

 

return reByte;

}

 

 

//public key를 가지고 오는 기능

private void getPublicKey(String pPublicKeyFile) throws FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException, IOException

{

publicKey = eccInstanceObject.readPublicKeyFromPemFile(pPublicKeyFile);

}

 

//public key를 가지고 오기 위해서 파일명을 입력하는 기능을 제공

private PublicKey putPublicKeyFile(String pPublicKeyFile) throws FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException, IOException

{

if(pPublicKeyFile ==null || STR_EMPTY.equals(pPublicKeyFile.trim())) 

{

System.out.println(" PublicKeyFile is null ");

return null;

}

 

getPublicKey(pPublicKeyFile);

 

return publicKey;

 

}

 

 

//입력한 자료에 대해서 서명이 올바른지 혹인 하는 기능

public boolean compareIntegrityValue(String pPlanText, byte[] pByteSignaturePrivate ,String pPublicKeyFile)  

{

boolean reBool = true;

 

try

{

PublicKey publicKey = putPublicKeyFile(pPublicKeyFile);

 

if(publicKey == null)

{

System.out.println(" PublicKey is null ");

reBool = false;

}

else

{

 byte[]  byteText = pPlanText.getBytes(STR_CHARSET);

 

 Signature signature;

 signature = Signature.getInstance(STR_ALGORITHM);

 

 // 검증할 때는 공개키 2를 이용해 복호화를 수행합니다.

 signature.initVerify(publicKey);   

 signature.update(byteText);

    

 reBool = signature.verify(pByteSignaturePrivate);

}

}

catch(Exception e)

{

e.printStackTrace();

}

 

return reBool;

}

 

 

 

 

 

}

 

'보안' 카테고리의 다른 글

java.exe 와 javaw.exe 의 차이점  (0) 2020.08.14
SelectSockets  (0) 2020.08.11
블럭 암호 공격  (0) 2020.08.07
Feistel SPN 구조  (0) 2020.08.05
블록 암호화와 운용방식  (0) 2020.08.05

관련글 더보기

댓글 영역