Android Rsa 데이터 복호화 에 대한 소개 및 사용 예시
RSA 는 현재 가장 영향력 있 는 공개 키 암호 화 알고리즘 으로 RSA 도 데이터 암호 화 와 디지털 서명 에 사용 할 수 있 는 첫 번 째 알고리즘 이다.이 알고리즘 은 매우 간단 한 수론 사실 을 바탕 으로 한다.두 개의 큰 소 수 를 곱 하 는 것 은 매우 쉽 지만 그 때 는 그 곱 하기 에 대해 인수 분 해 를 하려 고 했 지만 매우 어 려 웠 기 때문에 곱 하기 공 개 를 암호 화 키,즉 공개 키 로 할 수 있 고 두 개의 큰 소수 그룹 은 비밀 키 로 합성 할 수 있다.공개 키 는 발표 할 수 있 는 사람 이 사용 할 수 있 는 것 이 고 비밀 키 는 자신의 소유 이 며 복호화 에 사용 할 수 있 습 니 다.
RSA 알고리즘 원리
1.무 작위 로 두 개의 대질 수 p 와 q 를 선택 하고 p 는 q 와 같 지 않 으 며 N=pq 를 계산한다.
2.1 보다 작은 자연수 e 를 선택 하고 e 는(p-1)(q-1)과 호소해 야 합 니 다.
3.공식 으로 d:d 를 계산한다.×e = 1 (mod (p-1)(q-1)) 。
4.p 와 q 를 소각 합 니 다.
최종 적 으로 얻 은 N 과 e 는'공개 키'이 고 d 는'비밀 키'이다.발송 자 는 N 을 사용 하여 데 이 터 를 암호 화하 고 수신 자 는 d 를 사용 해 야 데이터 내용 을 풀 수 있다.
RSA 의 안전성 은 대수 분해 에 의존 하고 1024 비트 이하 의 N 은 안전 하지 않 은 것 으로 증명 되 었 으 며 RSA 알고리즘 이 모두 대수 계산 을 하기 때문에 RSA 가 가장 빠 른 상황 도 DES 보다 배 느 려 졌 다.이것 은 RSA 의 가장 큰 결함 이기 때문에 보통 소량의 데이터 나 암호 화 키 만 암호 화 할 수 있 지만 RSA 는 여전히 강도 가 높 은 알고리즘 이 라 고 할 수 있다.
Rsa 사용
우선 비밀 키 쌍 생 성
/**
* RSA
*
* @param keyLength , :512~2048
* 1024
* @return
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
return kpg.genKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
구체 적 인 암호 화 실현:공개 키 암호 화
/**
*
*
* @param data
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
//
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
//
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.ENCRYPT_MODE, keyPublic);
return cp.doFinal(data);
}
비밀 키 암호 화
/**
*
*
* @param data
* @param privateKey
* @return byte[]
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
//
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
//
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
return cipher.doFinal(data);
}
공개 키 복호화
/**
*
*
* @param data
* @param publicKey
* @return byte[]
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
//
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
//
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.DECRYPT_MODE, keyPublic);
return cipher.doFinal(data);
}
비밀 키 복호화
/**
*
*/
public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
//
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
//
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
byte[] arr = cp.doFinal(encrypted);
return arr;
}
전역 변수 설명:
public static final String RSA = "RSA";//
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//
public static final int DEFAULT_KEY_SIZE = 2048;//
public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // bufferSize, partSplit
public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;//
암호 화 충전 방식그 전에 이런 조작 으로 rsa 복호화 가 이 루어 질 줄 알 았 는데 만사 가 다 잘 될 줄 알 았 습 니 다.하하,이 일 은 아직 끝나 지 않 았 습 니 다.비극 이 발생 했 습 니 다.안 드 로 이 드 쪽 에서 암호 화 된 데 이 터 는 서버 측 에서 필사적으로 복호화 할 수 없습니다.원래 안 드 로 이 드 시스템 의 RSA 실현 은'RSA/NO/NoPadding'이 고 표준 JDK 실현 은'RSA/NO/PCS1Padding'입 니 다.이것 은 안 드 로 이 드 기기 에서 암호 화 된 후 서버 에서 복호화 할 수 없 는 원인 을 초래 하 였 으 므 로 이 를 실현 할 때 반드시 주의해 야 합 니 다.
세그먼트 암호 화 실현
충전 방식 을 해결 한 후에 자신 있 게 만사 가 잘 되 었 다 고 생각 했 습 니 다.그러나 의외 의 일이 발생 했 습 니 다.RSA 비대 칭 암호 화 내용 의 길 이 는 제한 이 있 습 니 다.1024 비트 key 는 최대 127 비트 의 데 이 터 를 암호 화 할 수 있 습 니 다.그렇지 않 으 면 잘못 보고 할 수 있 습 니 다(javax.crypto.IllegalBlock Size Exception:Data must be longer than 117 bytes).RSA 는 자주 사용 하 는 비대 칭 암호 화 알고리즘 입 니 다.최근 사용 할 때'부정 확 한 길이'의 이상 이 발생 했 는데 암호 화 된 데이터 가 너무 길 어서 그런 것 으로 나 타 났 다.RSA 알고리즘 에 따 르 면 암호 화 된 바이트 수 는 키 의 길 이 를 8 로 나 눈 다음 11(즉,KeySize/8-11)을 빼 면 안 되 고 암호 화 된 후에 비밀문서 의 바이트 수 를 얻 으 면 키 의 길이 값 을 8(즉,KeySize/8)로 나 눌 수 있 습 니 다.
공개 키 세그먼트 암호 화
/**
*
*
*/
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPublicKey(data, publicKey);
}
List<Byte> allBytes = new ArrayList<Byte>(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
비밀 키 세그먼트 암호 화
/**
*
*
* @param data
* @param privateKey
*/
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPrivateKey(data, privateKey);
}
List<Byte> allBytes = new ArrayList<Byte>(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
공개 키 세그먼트 복호화
/**
*
*
* @param encrypted
* @param publicKey
*/
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPublicKey(encrypted, publicKey);
}
int dataLen = encrypted.length;
List<Byte> allBytes = new ArrayList<Byte>(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// data
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// split[0]
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// data
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// split , break, split
isMatchSplit = true;
}
}
}
} else {
// split ,
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
비밀 키 세그먼트 복호화
/**
*
*
*/
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPrivateKey(encrypted, privateKey);
}
int dataLen = encrypted.length;
List<Byte> allBytes = new ArrayList<Byte>(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// data
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// split[0]
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// data
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// split , break, split
isMatchSplit = true;
}
}
}
} else {
// split ,
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
이렇게 해서 만 나 는 문 제 를 해결 했다.프로젝트 에서 사용 하 는 방안 은 클 라 이언 트 공개 키 암호 화,서버 비밀 키 복호화 이다.서버 개발 자 는 효율 적 인 고려 에서 나 온 것 이 라 고 해서 스스로 프로그램 을 써 서 진정한 효율 을 테스트 했다.STEP 1:대상 데이터 100 개 준비
List<Person> personList=new ArrayList<>();
int testMaxCount=100;//
//
for(int i=0;i<testMaxCount;i++){
Person person =new Person();
person.setAge(i);
person.setName(String.valueOf(i));
personList.add(person);
}
//FastJson json
String jsonData=JsonUtils.objectToJsonForFastJson(personList);
Log.e("MainActivity"," json ---->"+jsonData);
Log.e("MainActivity"," json ---->"+jsonData.length());
두 번 째 단계 비밀 키 쌍 생 성
KeyPair keyPair=RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE);
//
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
//
long start=System.currentTimeMillis();
byte[] encryptBytes= RSAUtils.encryptByPublicKeyForSpilt(jsonData.getBytes(),publicKey.getEncoded());
long end=System.currentTimeMillis();
Log.e("MainActivity"," cost time---->"+(end-start));
String encryStr=Base64Encoder.encode(encryptBytes);
Log.e("MainActivity"," json --1-->"+encryStr);
Log.e("MainActivity"," json --1-->"+encryStr.length());
//
start=System.currentTimeMillis();
byte[] decryptBytes= RSAUtils.decryptByPrivateKeyForSpilt(Base64Decoder.decodeToBytes(encryStr),privateKey.getEncoded());
String decryStr=new String(decryptBytes);
end=System.currentTimeMillis();
Log.e("MainActivity"," cost time---->"+(end-start));
Log.e("MainActivity"," json --1-->"+decryStr);
//
start=System.currentTimeMillis();
encryptBytes= RSAUtils.encryptByPrivateKeyForSpilt(jsonData.getBytes(),privateKey.getEncoded());
end=System.currentTimeMillis();
Log.e("MainActivity"," cost time---->"+(end-start));
encryStr=Base64Encoder.encode(encryptBytes);
Log.e("MainActivity"," json --2-->"+encryStr);
Log.e("MainActivity"," json --2-->"+encryStr.length());
//
start=System.currentTimeMillis();
decryptBytes= RSAUtils.decryptByPublicKeyForSpilt(Base64Decoder.decodeToBytes(encryStr),publicKey.getEncoded());
decryStr=new String(decryptBytes);
end=System.currentTimeMillis();
Log.e("MainActivity"," cost time---->"+(end-start));
Log.e("MainActivity"," json --2-->"+decryStr);
실행 결과:비교 결과:비밀 키 의 복호화 에 시간 이 많이 걸 리 기 때문에 서로 다른 수요 에 따라 복호화 할 수 없 는 방안 을 사용 할 수 있 습 니 다.개인 적 으로 서버 의 복호화 효율 이 높 고 클 라 이언 트 의 비밀 키 암호 화,서버 의 공개 키 복호화 가 좋 습 니 다.
암호 화 된 데이터 크기 의 변화:데이터 양 차 는 암호 화 전의 1.5 배 에 달 하지 않 습 니 다.
총결산
이상 은 안 드 로 이 드 Rsa 데이터 복호화 에 관 한 모든 내용 입 니 다.이 글 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.