종단 간 암호화
옥텟 API 사용 시 전송 구간 사이의 추가적인 보안을 위해 RSA 퍼블릭 키 기반의 종단 간 암호화 기능을 제공합니다. 고객은 퍼블릭 키를 이용해 암호화를 수행하고 옥텟 서버는 프라이빗 키를 이용해 복호화를 수행합니다.
![RSA 공개키.png 938](https://files.readme.io/b2925e4-RSA_.png)
그림 1 : 양측 수행 역할
RSA 키
암호화에 필요한 RSA 키 쌍은 오너 계정 생성 시 자동으로 생성됩니다. 고객사 측에서 사용할 RSA 퍼블릭 키는 옥텟 콘솔의 개발자 도구 페이지에서 확인할 수 있습니다.
암호화 대상
멀티시그 키 중 유저키를 암호화해야 합니다. 암호화 결과를 Request Body의 encryptedUserKey 필드에 담아 API를 호출하면, 옥텟 서버는 해당 값의 복호화 결과를 서명 시 사용합니다.
암호화하기
![RSA 공개키 암호화 방식 - 유저키.png 938](https://files.readme.io/3ee5328-RSA____-_.png)
그림 2 : 암호화하기
암호화 패딩 - OAEPWithSHA1AndMGF1Padding
암호화 예제 코드
고객사에서 수행해야 하는 RSA 퍼블릭 키를 활용한 암호화의 언어 별 예제 코드입니다.
node.js
const { readFileSync } = require('fs');
const { publicEncrypt } = require('crypto');
const publicKeyFilePath = '/Users/sam/Downloads/rsa-public-key.pem';
const multisigKey = '801... or 802...';
const publicKey = readFileSync(publicKeyFilePath);
const bodyBuffer = Buffer.from(multisigKey);
const encryptedMessage = publicEncrypt(publicKey, bodyBuffer).toString('base64');
console.log(encryptedMessage);
java 8 이상
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package EncryptBody;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.Cipher;
public class App {
private static String readPemFile(String filePath) {
StringBuffer sb = null;
try (
FileInputStream is = new FileInputStream(filePath);
Scanner sc = new Scanner(is, "UTF-8");
) {
sb = new StringBuffer();
while (sc.hasNextLine()) {
sb.append(sc.nextLine());
}
if (sc.ioException() != null) {
throw sc.ioException();
}
} catch(FileNotFoundException e) {
System.err.println("File not found");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String result = sb.toString()
.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "");
sb.setLength(0);
return result;
}
private static RSAPublicKey getPublicKey(String pem) {
byte[] decoded = null;
KeyFactory kf = null;
RSAPublicKey publicKey = null;
try {
decoded = Base64.getDecoder().decode(pem);
kf = KeyFactory.getInstance("RSA");
publicKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(decoded));
} catch (IllegalArgumentException e) {
System.err.println("Invalid pem file");
e.printStackTrace();
} catch (GeneralSecurityException e) {
System.err.println("PublicKey generation failed");
e.printStackTrace();
}
return publicKey;
}
private static String encrypt(String plainText, RSAPublicKey publicKey) {
String result = null;
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
result = Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes()));
} catch (GeneralSecurityException e) {
System.err.println("PublicKey encryption failed");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String publicKeyFilePath = "/Users/sam/Downloads/rsa-public-key.pem";
String multisigKey = "801... or 802...";
String pem = readPemFile(publicKeyFilePath);
RSAPublicKey publicKey = getPublicKey(pem);
String encrypted = encrypt(multisigKey, publicKey);
System.out.println(encrypted);
}
}
C#
using System.Security.Cryptography;
using System.Text;
string publicKeyFilePath = "/Users/sam/Downloads/rsa-public-key.pem";
string multisigKey = "801... or 802...";
RSACryptoServiceProvider rsa = new();
rsa.ImportFromPem(File.ReadAllText(publicKeyFilePath));
byte[] encrypted = rsa.Encrypt(Encoding.UTF8.GetBytes(multisigKey), true);
Console.WriteLine(Convert.ToBase64String(encrypted));
Python 3
#
# pip3 install pycryptodome
#
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
def readPemFile(file_path) :
file = open(file_path)
key = RSA.importKey(file.read())
file.close()
return key
public_key_file_path = '/Users/sam/Downloads/rsa-public-key.pem'
multisig_key = '801... or 802...'
cipher = PKCS1_OAEP.new(readPemFile(public_key_file_path))
encrypted = cipher.encrypt(multisig_key.encode('utf-8'))
print(base64.b64encode(encrypted).decode('ascii'))
Updated 11 months ago