Created
July 12, 2016 09:54
-
-
Save teruteru128/14c835d906d468154303fd3d0c8c6678 to your computer and use it in GitHub Desktop.
JavaでRSA鍵ペアを生成してみた@鍵ペア検証コード付き ref: http://qiita.com/teruteru128/items/b02078b115f3fdd3e1ac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
素数生成完了 | |
p : 11986036157968132346520837773856659201839110728802035511508317831681007979436002145500826499755663463491872944597086946814559027949874736415090464605880137 | |
q : 9937658523438649360213691713305392768344928118607991280259811429812816516088395721590675912116362768528361503738754901598727081542350764090985811794454401 | |
n : 119113134387475851867985689657000237177931905808165300526766493837814859856182158624264860506081520590229037346555991460737484576589634306133175864861578710606314396664765864609431629037347673593139937885276064477678386183356481130329007362710327345476281951711747292607172340202378498591050053012312318132937 | |
n bit length : 1024 | |
-------------------------------------------------------------- | |
d : 7637111718512802379560795702255443438388541864990930204517643577009903430362656675452964643583846522119450309447003618078625969922786263551453453532330647570751911798130055257188134949112601213437337415154759051002112119038305133224325974939586200458322929216589258225550317239149829329203948856756075599873 | |
4418EBA57209FED2C9B852673EF6D42F320066EC1B0175B2AF4B3E103F3B2719684CF39811D8BA6E2F8A455DD621079B7C0ACBB7ADCA368806BED51097822CCF05F72D8E9F001737EF3FE9993CCC62E4C1F87585CF95FF4639579150254DD2D4C995DD8A84848035DA7C3364EFAF922903CC96191E6E32763E13852CDA965BBE | |
テストてすとテストてすとテストてすとテストてすと | |
true | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.math.BigInteger; | |
import java.security.KeyFactory; | |
import java.security.PrivateKey; | |
import java.security.PublicKey; | |
import java.security.SecureRandom; | |
import java.security.spec.RSAPrivateKeySpec; | |
import java.security.spec.RSAPublicKeySpec; | |
import javax.crypto.Cipher; | |
import javax.xml.bind.DatatypeConverter; | |
/** | |
* RSA鍵ペア生成 | |
*/ | |
public class Main { | |
/** | |
* */ | |
private static final String CIPHER_ALGORITHM = "RSA"; | |
/** | |
* */ | |
private static final String CIPHER_MODE = CIPHER_ALGORITHM + "/ECB/PKCS1PADDING"; | |
public static void main(String[] args) throws Exception { | |
/** 平文 */ | |
String plainText = "テストてすとテストてすとテストてすとテストてすと"; | |
/** 素数生成源 */ | |
SecureRandom rnd = SecureRandom.getInstanceStrong(); | |
/** セキュリティパラメータ(nのビット長) */ | |
int nBitLength = 1 << 10; | |
/** pのビット長 */ | |
int pBitLength = (nBitLength >> 1) + (nBitLength & 0x01); | |
/** qのビット長 */ | |
int qBitLength = nBitLength >> 1; | |
/** | |
* 素数確実度 数値が大きいほど素数である確率が高くなる (代わりに実行時間が長くなる) | |
*/ | |
int certainty = 100; | |
/** 素数q */ | |
BigInteger p = null; | |
/** 素数q */ | |
BigInteger q = null; | |
/** */ | |
BigInteger n = null; | |
/** Φ(n) 1からnまでの自然数のうち n と互いに素なものの個数 */ | |
BigInteger phiN = null; | |
/** 公開指数 決め打ち */ | |
BigInteger publicExponent = BigInteger.valueOf(65537L); | |
/** 非公開指数 */ | |
BigInteger d = null; | |
/* 素数p生成 */ | |
p = new BigInteger(pBitLength, certainty, rnd); | |
do { | |
do { | |
/* 素数q生成 */ | |
q = new BigInteger(qBitLength, certainty, rnd); | |
} while (p.equals(q)); | |
/* qがpと等しい場合は再生成 */ | |
/* p < q ならばpとqを入れ替える */ | |
if (p.compareTo(q) < 0) { | |
BigInteger tmp = q; | |
q = p; | |
p = tmp; | |
} | |
n = p.multiply(q); | |
} while (n.bitLength() != nBitLength); | |
/* nのビット長がセキュリティパラメータに達しない場合素数を再生成 */ | |
System.out.println("素数生成完了"); | |
System.out.printf("p : %d%n", p); | |
System.out.printf("q : %d%n", q); | |
System.out.printf("n : %d%n", n); | |
System.out.printf("n bit length : %d%n", n.bitLength()); | |
System.out.println("--------------------------------------------------------------"); | |
/* Φ(n)=(p-1)(q-1) */ | |
phiN = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)); | |
/* (d * publicExponent) ≡ 1 mod Φ(n) を満たす dを求める */ | |
d = publicExponent.modInverse(phiN); | |
System.out.printf("d : %d%n", d); | |
/* ここまでで鍵ペア生成完了 以下暗号化テスト */ | |
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(n, d); | |
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, publicExponent); | |
KeyFactory factory = KeyFactory.getInstance("RSA"); | |
PrivateKey privateKey = factory.generatePrivate(privateKeySpec); | |
PublicKey publicKey = factory.generatePublic(publicKeySpec); | |
byte[] cipher = encryptionTest(plainText.getBytes(), publicKey); | |
System.out.println(DatatypeConverter.printHexBinary(cipher)); | |
byte[] decryptedText = decryptionTest(cipher, privateKey); | |
String restoredText = new String(decryptedText); | |
System.out.println(restoredText); | |
System.out.println(plainText.equals(restoredText)); | |
} | |
/* 暗号化テスト */ | |
static byte[] encryptionTest(byte[] plainText, PublicKey key) throws Exception { | |
Cipher cipher = Cipher.getInstance(CIPHER_MODE); | |
cipher.init(Cipher.ENCRYPT_MODE, key); | |
return cipher.doFinal(plainText, 0, plainText.length); | |
} | |
/* 復号テスト */ | |
static byte[] decryptionTest(byte[] cipherText, PrivateKey key) throws Exception { | |
Cipher cipher = Cipher.getInstance(CIPHER_MODE); | |
cipher.init(Cipher.DECRYPT_MODE, key); | |
return cipher.doFinal(cipherText, 0, cipherText.length); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment