Chapter 9 Writing a Provider 데이타베이스 실험실 강 민 석 [email protected].
-
Upload
alban-bruce -
Category
Documents
-
view
226 -
download
6
Transcript of Chapter 9 Writing a Provider 데이타베이스 실험실 강 민 석 [email protected].
DB Lab. 2 Kang Minsuk
Contents
Getting Start
Adding the ElGamal Classes
ElGamal
Generating Keys
Signature
Cipher
DB Lab. 3 Kang Minsuk
Provider
ProvidersProgram
MessageDigestSecurity2. MD5 를 구현한 message digest 객체
요구
5. 여기 instance 가 있습니다.
3. 누가 MD5 message digest
class 를 가지고 있나 ?
4. sun.security.provider.
MD5 class 입니다 .
1.MD5 알고리즘을 구현한 instance 를 주세요
6. 여기 있습니다.
MessageDigest.getInstance(“MD5”)
DB Lab. 4 Kang Minsuk
Getting Started(Algorithm Names and Implementations)
알고리즘 이름을 클래스 이름으로 mapping
DES/CBC/PKCS5Padding : oreilly.jonathan.crypto.CBCWrapper
DES/CFB/NoPadding : oreilly.jonathan.crypto.CFBWrapper
Cipher.DES/CBC/PKCS5Padding : oreilly.jonathan.crypto.CBCWrapper
Cipher.DES/CFB/NoPadding : oreilly.jonathan.crypto.CFBWrapper
Cryptographic provider 여러 종류의 알고리즘을 포함 할 수 있음
key pair generation, signatures, cipers,.. 알고리즘 이름은 type and name 으로 만들어짐
DB Lab. 5 Kang Minsuk
A Simple Provider
Subclass 생성 CBCWrapper, CFBWrapper classes 에 대한 mapping 을 포함 하는
subclass 생성 oreilly.jonathan.security.provider
package oreilly.jonathan.crypto;import java.security.*;public class Provider extends java.security.Provider { public Provider() { super ("Jonathan", 1.2, "Jonathan's Cryptography Provider"); put("Cipher.DES/CBC/PKCS5Padding", "oreilly.jonathan.crypto.CBCWrapper"); put("Cipher.DES/CFB/Nopadding",
"oreilly.jonathan.crypto.CFBWrapper"); } }
Provider name 을 받아들이는getInstance() 메소드에서 이용됨
DB Lab. 6 Kang Minsuk
An Algorithm by Any Other Name
다른 알고리즘 name 으로 같은 구현을 return sun provider 에서 다음은 같은 message digest 구현을 얻음
MessageDigest one = MessageDigest.getInstance("SHA-1");MessageDigest two = MessageDigest.getInstance("SHA");
Class 가 8 bit CFB 모드이기 때문에 CFBWrapper 와 연결하기 위한 “ DES/CFB8/NoPadding” 을 원할 경우
Put(“Alg.Alias.Cipher.DES/CFB8/NoPadding” , “DES/CFB/NoPadding”);
우리의 provider 에서 다음은 같은 결과를 초래
Cipher one = Cipher.getInstance("DES/CFB8/NoPadding");Cipher two = Cipher.getInstance("DES/CFB/NoPadding");
DB Lab. 7 Kang Minsuk
Installing the Provider
security.provider.1 = sun.security.provider.Sunsecurity.provider.2 = com.sun.crypto.provider.SunJCEsecurity.provider.3 = oreilly.jonathan.crypto.Providersecurity.provider.4 = cryptix.security.Cryptixsecurity.provider.5 = iaik.security.provider.IAIK
~/Lib/security/java.security 파일 수정
Application 에서 runtime 시 Jonathan Provider 를 추가하는 방법
java.security.Provider p = new oreilly.jonathan.security.Provider();Security.addProvider(p);
DB Lab. 8 Kang Minsuk
Adding the ElGamal Classes
Jonathan provider 의 class
oreilly.jonathan.crypto.ElGamalKeyPairGenerator oreilly.jonathan.crypto.ElgamalSignature oreilly.jonathan.crypto.ElGamalCipher
Adding the Provider(ElGamal) Classespackage oreilly.jonathan.crypto;import java.security.*;public class Provider extends java.security.Provider { public Provider( ) { super("Jonathan", 1.2, "Jonathan's Cryptography Provider");
put("KeyPairGenerator.ElGamal", "oreilly.jonathan.crypto.ElGamalKeyPairGenerator");
DB Lab. 9 Kang Minsuk
put("Cipher.ElGamal",
"oreilly.jonathan.crypto.ElGamalCipher");
put("Signature.ElGamal",
"oreilly.jonathan.crypto.ElGamalSignature");
put("Cipher.DES/CBC/PKCS5Padding",
"oreilly.jonathan.crypto.CBCWrapper");
put("Cipher.DES/CFB/NoPadding",
"oreilly.jonathan.crypto.CFBWrapper");
put("Alg.Alias.Cipher.DES/CFB8/NoPadding",
"DES/CFB/NoPadding");
}
}
Cont’d
DB Lab. 10 Kang Minsuk
ElGamal 알고리즘의 이용
ciphertext plaintextplaintextcipher cipher
Encryption Decryption
ElGamal 알고리즘 이용
DB Lab. 11 Kang Minsuk
ElGamal(Key pair Generation)
Random prime p 를 생성 (modulus 라 불림 ) p size 는 key size 와 같다 . Ex. : 2048 bit key has a P that is 2048 bit
Random number g, x 선택 g, x < p
x is private key
y = gx mod p 계산 p, g, y are public key
DB Lab. 12 Kang Minsuk
Signature 생성 단계
p - 1 과 서로소인 난수 k 를 선택 k 와 p-1 은 1 을 제외한 공통인수가 없음
a 와 b 를 계산
signature 확인
a = gk mod p b = ((m-xa) / k) mod (p-1)* m 은 메시지이고 a,b 는 signature
yaab mod p = gm mod p 를 검사
K 는 공개 되서는 안됨
DB Lab. 13 Kang Minsuk
Cont’d
공개키 : y =3, g =2, p = 11
예 ) p=11, g =2 , x = 8 라면y = gx mod p = 28 mod 11 = 3
인증 (signature)
난수 k = 9 를 선택 , m = 5 라 할 때 a = gk mod p = 29 mod 11 = 6b = ((m-xa) / k) mod (p-1) = ((5-8*6) / 9) mod 10 = 3
yaab mod 11 = gm mod p
3663 mod 11 = 9, 25 mod 11 = 9
인증 (signature) 확인
암호화 (Cipher)
난수 k = 9 를 선택 , m = 5
a= gk mod p = 29 mod 11 = 6 b= yk m mod p = 39 * 5 mod 11 = 9
복호화
m = ( b / ax ) mod P
DB Lab. 14 Kang Minsuk
Cipher
p - 1 과 서로소인 난수 k 를 선택 암호문 a 와 b 를 계산
복호 (decrypt) 를 위해 m = ( b / ax ) mod P 를 계산
( b / ax ) mod p = ((yk * m) / gkx ) mod p
= ((gkx * m) / gkx ) mod p
= m mod p
a = gk mod p b = yk * m mod p
* m 은 평문 , 숫자 a 와 b 는 암호문 (modulus p 보다 2 배 큼 )
DB Lab. 15 Kang Minsuk
Generating Keys(key Classes)
ElGamal 의 공개키 (p, g) 생성package oreilly.jonathan.crypto;import java.math.BigInteger; // 모든 수학적인 계산을 수행함import java.security.*;
public class ElGamalKey implements Key { private BigInteger mP, mG; protected ElGamalKey (BigInteger g, BigInteger p) mG=g; mP=p; } protected BigInteger getG( ) { return mG ; } protected BigInteger getP( ) { return mP; }
public String getAlgorithm( ) { return "ElGamal"; } public String getFormat( ) { return "NONE"; } public byte[] getEncoded( ) { return null; } }
공개키 p, g, y개인키 x
DB Lab. 16 Kang Minsuk
Cont’d
공개키 y 를 포함하는 Public key class 생성package oreilly.jonathan.crypto ; import java.math.BigInteger ;import java.security.* ;
public class ElGamalPublicKey extends ElGamalKey implements PublicKey { private BigInteger mY;
protected ElGamalPublicKey(BigInteger y, BigInteger g, BigInteger p) { super(g, p); mY=y; }
protected BigInteger getY() return mY; }
DB Lab. 17 Kang Minsuk
Cont’d
ElGamalPrivateKey x 생성
packgae oreilly.jonathan.crypto;import java.math.BigInteger;import java.security.*;
public class ElGamalPrivateKey extends ElGamalKey implements PrivateKey { private BigInteger mX ;
protected ElGamalPrivateKey(BigInteger x, BigInteger g, BigInteger p) { super(g, p) ; mX= x ; }
protected BigInteger getX() return mX; }
DB Lab. 18 Kang Minsuk
ElGamal Key Pair Generator
package oreilly.jonathan.crypto;
import java.math.BigInteger;import java.security.*;
public class ElGamalKeyPairGenerator extends KeyPairGeneratorSpi { private int mStrength = 0; private SecureRandom mSecureRandom = null;
// Strength is interpreted as the bit length of p. public void initialize(int strength, SecureRandom random) { mStrength=strength; mSecureRandom=random; }
Strength 와 SecureRandom 의 측정으로 초기화됨
DB Lab. 19 Kang Minsuk
public KeyPair generateKeyPair( ) { if (mSecureRandom==null) { /* default 처리 */ mStrength=1024; mSecureRandom=new SecureRandom( ); }
BigInteger p=new BigInteger (mStrength, 16, mSecureRandom); BigInteger g=new BigInteger (mStrength, -1, mSecureRandom); BigInteger x=new BigInteger (mStrength, -1, mSecureRandom); BigInteger y=g.modPow(x, p); // y 값 계산
ElGamalPublicKey publicKey = new ElGamalPublicKey(y, g, p); ElGamalPrivateKey privateKey = new ElGamalPrivateKey(x, g, p); return new KeyPair(publicKey, privateKey); } }
Cont’d
소수가 될 확률 : 1- 0.516
DB Lab. 20 Kang Minsuk
package oreilly.jonathan.crypto ;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.sercurity.*;
public class ElGamalSignature
extends SignatureSpi {
protected ElGamalKey mKey ; /* 나중에 서명 값을 생성 또는 확인할 key 저장 */
protected ByteArrayOutputStream mOut; /* data 저장 - 서명 값 생성 또는 확인 시 이용함 */
protected static BigInteger kOne = BigInteger.valueOf(1) ;
Signature
ElGamal signature class 를 구현하기 위하여 signature 의 SPI 를 구현함
DB Lab. 21 Kang Minsuk
protected void engineInitVerify(PublicKey key) throws InvalidKeyException { if ( !(key instanceof ElGamalPublicKey)) throw new InvalidKeyException(”I didn'd get an ElGamalPublicKey.")"; mKey = (ElGamalKey)key; mOut = new ByteArrayOutputStream( ); }
protected void engineInitSign(PrivateKey key) throws InvalidKeyException { if ( !(key instanceof ElGamaPrivateKey)) throw new InvalidKeyException("I didn't get an ElGamalPrivateKey."); mKey = (ElGamalKey)key; mOut = new ByteArrayOutputStream( ); }
Cont’d서명의 initVerify() 호출 시
이 메소드가 호출됨
서명의 initsign( ) 호출 시이 메소드가 호출됨
DB Lab. 22 Kang Minsuk
//signature’s update( ) 메소드 호출시 호출됨protected void engineUpdate(byte b) throws SignatureException { mOut.write(b) ; }
protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { mOut.write(b, off, len); } //Signature API 에 있는 sign() 와 동등한 SPIprotected byte[] engineSign() throws SignatureException {
BigInteger x = ((ElGamalPrivateKey)mKey).getX();BigInteger g = mKey.getG();BigInteger p = mKey.getP();BigInteger pminusone = p.subtract(kOne); // p-1 값 계산
Cont’d
ByteArrayOutputStream 에 input data 기록
DB Lab. 23 Kang Minsuk
BigInteger k ; // 랜덤한 k 값 선택 do { k = new BigInteger(p.bitLength() - 1, new SecureRamdom()); } while (k.gcd(pminusone).equals(kOne) == false); // ByteArrayOutputStream 에 저장된 모든 byte 를 BingInterger m 으로 변환 BigInteger m = new BigInteger(1, mOut.toByteArray());
// 서명이 a, b 의 계산에 의해 표현 BigInteger a = g.modPow(k, p); BigInteger top = m.subtract(x.multiply(a)).mod(pminusone); BigInteger b = top.multiply( k.modPow(kOne.negate( ) , pminusone)).mod(pminusone);
Cont’d
DB Lab. 24 Kang Minsuk
int modulusLength = (p.bitLength() + 7) /8; byte[] signature = new byte[modulusLength * 2]; byte[] aBytes = getBytes(a); int aLength = aBytes.length; byte[] bBytes = getBytes(b); int bLength = bBytes.length; System.arraycopy(aBytes, 0, signature, modulusLength - aLength, aLength); System.arraycopy(bBytes, 0, signature, modulusLength * 2 - bLength, bLength); return signature ; }
protected boolean engineVerify(byte[] sigBytes) throws SignatureException { BigInteger y = ((ElGamalPublicKey).getY(); Biginteger g = mKey.getG(); BigInteger p = mKey.getP();
Modulus p 의 두배 만큼 배열을 할당하고 a, b 값을 저장
공개키로부터 매개변수 추출
DB Lab. 25 Kang Minsuk
// a, b 를 추출하기 위하여 BigInteger 생성 int modulusLength = (p.bitLength() + 7) / 8 ; byte[] aBytes = new byte[modulusLength] ; byte[] bBytes = new byte[modulusLength] ; System.arraycopy(sigBytes, 0, aBytes, 0, modulusLength) ; System.arraycopy(sigBytes, modulusLength, bBytes, 0, moduluslength) ; BigInteger a = new BigInteger(1, aBytes) ; BigInteger b = new BigInteger(1, bBytes) ; BigInteger first = y.modPow(a,p).multiply(a.modPow(b, p)).mod(p) ;
// 서명의 정확성 검사 루틴 BigInterger m = new BigInteger(1, mOut.toByteArray()) ; BigInteger second = g.modPow(m,p) ;
return first.equals(second) ; }
Cont’d
DB Lab. 26 Kang Minsuk
protected byte[] getBytes(BigInteger big) { byte[] bigBytes = big.toByteArray( ); if ((big.bitLength( ) % 8) != 0) { return bigBytes ; } else { byte[] smallerBytes = new byte[big.bitLength() / 8] ; System.arraycopy(bigBytes, 1, smallerByters, 0, smallerByters.length) ; return smallerBytes ; } }
/*ElGamalSignature 는 parameter 를 이용하지 않음 . 하지만 이것을 정의하지 않으면 SignatureSpi 의 subclass 를 생성할 수 없음 */protected void engineSetParameter ( String param, Object value) throws InvalidParameterException { } protected object engineGetParameter(String param) throws InvalidParameterException { return null ; } }
Cont’dBigInteger 값을 갖는
byte 배열 return
DB Lab. 27 Kang Minsuk
Cipher
ciphertext
Decrypted plaintext
plaintext
ElGamalDecryption
ElGamalEncryption
0 00
암호화 Key(p) size 의 2 배
Public Key
Public Key
DB Lab. 28 Kang Minsuk
package oreilly.jonathan.crypto;import java.math.BigInteger;import java.security.* ;import java.security.spec.* ;import javax.crypto.* ;
public class ElGamalCipher extends BlockCipher { protected int mState ; protected Key mKey ; protected SecureRandom mSecureRandom ; protected int mPlainBlockSize ; protected int mCihperBlockSize ;
Cipher
Java.crypto.CipherSpi 를 확장한 class.oreilly.jonathan.crypto packag 에 있음
초기화 될때 ElGamalCipher 에게 전달됨
DB Lab. 29 Kang Minsuk
Cont’d protected void engineSetMode(String mode) throws NoSuchAlgorithmException { throw new NoSuchAlgorithmException("ElGamalCipher supports no modes.") ; } // padding 과 no mode 를 지원하기 때문에 engineSetMode 와 engineSetPadding 는 호출 시 바로 예외 처리로 감 // protected void engineSetPadding(String padding) throws NoSuchPaddingException { throw new NoSuchPaddingException("ElGamalCipher supports no padding.") ; }
protected int engineGetBlockSize( ) { // cipher 의 상태를 근거로한 if ( mState == Cipher.DECRYPT_MODE ) // 적당한 크기를 return return mCipherBlockSize ; else return mPlainBlockSize ; }
DB Lab. 30 Kang Minsuk
ciphertext
Decrypted plaintext
plaintext
ElGamalDecryption
ElGamalEncryption
0 00
암호화 Key(p) size 의 2 배
Public Key
Public Key
ElGamalCipher 에서의 Block handling
DB Lab. 31 Kang Minsuk
protected int engineGetOutputSize(int inLen) { int inBlocks ; int outLength ; if (mState == Cipher.ENCRYPT_MODE) { inBlocks = ( inLen + getBufferedDataLength() + mPlainBlockSize - 1) / mPlainBlockSize ; outLength = inBlocks * mCipherBlocksize ; } else { inBlocks = (inLen + getBufferedDataLengrh() + mCipherBlockSize - 1) / mCipherBlockSize ; outLength = inBlocks * mPlainBlockSize ; } return outLength ; } protected byte[] engineGetIV( ) { return null ; } //ElGamal 은 ECB mode 에서만 작동 하기 때문에 null 값을 return
Cont’d
Output buffer size 의 계산
DB Lab. 32 Kang Minsuk
// block 크기를 계산하기 위하여 calculateBlockSize() 메소드 이용 protected void engineInit ( int opmode, Key key, SecureRandom random) throws InvalidkeyException { if ( opmode == Cipher.ENCRYPT_MODE ) if ( !(key instanceof ElGamalPublicKey)) throw new InvalidkeyException("I didn't get an ElGamalPublicKey."); else if (opmode == Cipher.DECRYPT_MODE) if ( !(key instanceof ElGamalPrivatekey)) throw new InvalidKeyException("I didn't get an ElGamalPrivatekey.") ; else throw new IllegalArgumentException("Bad mode: " + opmode); // key 값이 정확한지 검사 mState = opmode; mKey = key; mSecureRandom = random ; calculateBlockSizes(key) ; } // block 크기를 계산하기
Cont’d
DB Lab. 33 Kang Minsuk
protected void engineInti(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgoritmParameterException { engineInit(opmode, key, random); // 이전에 오버로드 된 버전만 호출 } protected void calculateBlockSizes(Key key) { int modulusLength = (( ElGamalKey)key).getP().bitLength() ; mPlainBlockSize = (modulusLength - 1) / 8 ; mCipherBlockSize = ((modulusLength + 7) / 8) * 2 ; }// 암호 초기화 이전에 평문과 암호문의 크기 계산
Cont’d
DB Lab. 34 Kang Minsuk
protected int engineTransformBlock(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset ) throws ShortBufferException { If ( mState == Cipher.ENCRYPT_MODE) return encryptBlock(input, inputOffset, inputLength, output, outputOffset); else if (mState == Cipher.DECRYPT_MODE) return decryptBlock ( input, inputOffset, inputLength, output, outputOffset ) ; return 0 ; } // no padding 을 지원하기 때문에 두 메소드는 같은 역할
protected int engineTransformBlockFinal(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset ) throws ShortBufferException { If ( inputLength == 0 ) return 0 ; return engineTransformBlock(input, inputOffset, InputLength, output, outputOffset) ; }
Cont’d
DB Lab. 35 Kang Minsuk
protected int encryptBlock ( byte[] in, int inOff, int inLen, byte[] out, int outOff) { byte[] messageBytes = new byte[mPlainBlockSize] ; int inputLength = Math.min(mPlainBlockSize, inLen) ; System.arraycopy(in, inOff, messageBytes, 0, inputLength) ; BigInteger m = new BigInteger(1, messageBytes) ;
ElGamalPublicKey key = (ElGamalPublicKey)mKey ; BigInteger p = key.getP() ; BigInteger one = BigInteger.valueOf(1) ; BigInteger pminusone = p.subtract(one) ; BigInteger k ; // k 생성 do { k = new BigInteger ( p.bitLength() - 1, mSecureRandom) ; } while (k.gcd(pminusone).equals(one) == false) ;
Cont’dInput byte 로부터
message value 생성
DB Lab. 36 Kang Minsuk
BigInteger a = key.getG().modPow(k, p); //a, b 계산 BigInteger b = key.getY().modPow(k, p).multiply(m).mod(p) ;
byte[] aBytes = getBytes(a) ; // a, b 를 output buffer 에 복사 byte[] bBytes = getBytes(b) ;
System.arraycopy(aBytes, 0, out, outOff + mCipherBlockSize / 2
- aBytes.length, aBytes.length) ;
System.arraycopy(bBytes, 0, out, outOff + mCipherBlockSize
- bBytes.length, bBytes.length);
return mCipherBlockSize ; // encryptBlock() 은 쓰여진 암호문 byte 의 // 수를 return
}
Cont’d
DB Lab. 37 Kang Minsuk
protected int decryptBlock(byte[] in, int inOff, int inLen, // 복호처리 byte[] out, int outOff ) { //pull out our key ElGamalPrivateKey key = (ElGamalPrivateKey)mKey ; BigInteger p = key.getP() ;
// Extract a and b byte[] aBytes = new byte[mCipherBlockSize / 2] ; System.arraycopy(in, inOff, aBytes, 0, mCipherBlockSize / 2) ; byte[] bBytes = new byte[mCipherBlockSize / 2 ] ; System.arraycopy(in, inOff + mCipherBlockSize / 2, bBytes, 0, mCipherBlockSize /2) ; BigInteger a = new BigInteger(1, aBytes) ; BigInteger b = new BigInteger(1, bBytes) ; // 메시지 m 계산 BigInteger m = b.multiply(a.modPow(key.getX().negate(), p)).mod(p) ;
Cont’d
DB Lab. 38 Kang Minsuk
byte[ ] messageBytes = getBytes(m) ; int gatedLength = Math.min(messageBytes.length, mPlainBlockSize) ; System.arraycopy(messageBytes, 0, out,
outOff + mPlainBlockSize - gatedLength, gatedlength ) ; return mPlainBlockSize ; // 메시지 값의 byte 를 output buffer 에 복사 } // 복호된 byte 의 수를 return protected byte[ ] getBytes( BigInteger big ) { byte[ ] bigBytes = big.toByteArray(); if (( big.bitLength() % 8 ) !=0 ) { return bigBytes ; } else { byte[ ] smallerBytes = new byte[big.bitLenth() / 8 ] ; System.arraycopy(bigBytes, 1, smallerBytes, 0, smallerBytes.length ) ; return smallerBytes ; } }}
Cont’d
DB Lab. 39 Kang Minsuk
추후 연구
Padding 기법 구현 복호된 평문이 이전의 원문과 같아 지도록
예외처리를 향상 시켜라 .
encryptBlcok( ) method
decryptBlock( ) method