Android 데이터 암호 화 Rsa 암호 화
최근 에 동료 들 과 데이터 안전 전송 문 제 를 교류 할 의사 가 없 었 습 니 다.자신 이 사 용 했 던 Rsa 비대 칭 암호 화 알고리즘 을 떠 올 리 고 한가 로 이 정리 해 보 세 요.
기타 몇 가지 암호 화 방식:
•Android 데이터 암호 화 Rsa 암호 화
•Android 데이터 암호 화 Aes 암호 화
•Android 데이터 암호 화 Des 암호 화
•Android 데이터 암호 화 MD5 암호 화
•Android 데이터 암호 화 Base 64 인 코딩 알고리즘
•Android 데이터 암호 화 SHA 보안 해시 알고리즘
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
*
* @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 복호화 를 실현 할 수 있 을 것 이 라 고 생각 했 습 니 다.만사 가 다 잘 될 것 이 라 고 생각 했 습 니 다.하하,이 일 은 아직 끝나 지 않 았 습 니 다.비극 이 발생 했 습 니 다.Android 쪽 에서 암호 화 된 데 이 터 는 서버 측 에서 필사적으로 복호화 할 수 없습니다.원래 안 드 로 이 드 시스템 의 RSA 는'RSA/NO/NoPadding'이 고 표준 JDK 실현 은'RSA/NO/PKCS 1 Padding'입 니 다.이것 은 안 드 로 이 드 기기 에서 암호 화 된 후 서버 에서 복호화 할 수 없 는 원인 을 초래 하 였 으 므 로 이 를 실현 할 때 반드시 주의해 야 합 니 다. 세그먼트 암호 화 실현:충전 방식 을 해결 한 후에 만사 가 다 잘 되 었 다 고 자신 합 니 다.그러나 의외 의 일이 발생 했 습 니 다.RSA 비대 칭 암호 화 내용 의 길이 가 제한 되 어 있 습 니 다.1024 비트 key 의 최대 127 비트 데이터 만 암호 화 할 수 있 습 니 다.그렇지 않 으 면 오류 가 발생 할 수 있 습 니 다(javax.crypto.IllegalBlock Size Exception:Data must not 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 배 에 달 하지 않 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.