- damo-manager Gradle 프로젝트 초기 구성
- scpdb 부재 시 fake 모드 자동 fallback - ScpEncB64/DecB64/HashB64 래핑 + 유틸 보존 - RealBridge 격리로 NoClassDefFoundError 방지 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
|||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
bin/
|
||||||
|
out/
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
# damo-manager
|
||||||
|
|
||||||
|
Penta scpdb 라이브러리 래퍼. **단일 jar (`damo-manager.jar`)** 로 운영/로컬 양쪽 환경에서 동작한다.
|
||||||
|
|
||||||
|
- **운영**: 클래스패스에 `com.penta.scpdb.ScpDbAgent` 가 존재 → 실제 `ScpEncB64` / `ScpDecB64` / `ScpHashB64` 호출
|
||||||
|
- **로컬 개발**: scpdb 라이브러리 없음 → 자동으로 **fake 모드** 진입, 시작 시 `System.err` 에 강한 경고 배너 출력. 암복호화는 단순 Base64 round-trip, 해시는 JRE `MessageDigest` 로 대체
|
||||||
|
|
||||||
|
## 빌드
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd damo-manager
|
||||||
|
gradle clean build # 또는 ./gradlew clean build (wrapper 추가 시)
|
||||||
|
ls build/libs/ # damo-manager.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
JDK 8 toolchain 을 요구한다 (`build.gradle` 의 `JavaLanguageVersion.of(8)`). `JAVA_HOME` 이 JDK 8 이거나 Gradle 이 시스템에서 JDK 8 을 auto-detect 할 수 있어야 한다.
|
||||||
|
|
||||||
|
Fake 모드 스모크 검증:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gradle runFakeSmoke
|
||||||
|
```
|
||||||
|
|
||||||
|
## 소스 코드 커스터마이즈
|
||||||
|
|
||||||
|
`src/main/java/com/eactive/apim/custom/djb/damomanager/DamoManager.java` 상단 상수 영역을 수정한다.
|
||||||
|
|
||||||
|
| 상수 | 의미 | 기본값 |
|
||||||
|
|---|---|---|
|
||||||
|
| `INI_FILE` | scpdb 에 전달할 ini 경로 | `/prod/damo/ba_scp/scpdb_agent.ini` |
|
||||||
|
| `KEY` | `ScpEncB64`/`ScpDecB64` 의 키 이름 | `KEY1` |
|
||||||
|
| `CHARSET` | scpdb 호출 시 charset 인자 | `EUC-KR` |
|
||||||
|
| `SHA256`, `SHA512` | 해시 type 상수 | `71`, `73` |
|
||||||
|
|
||||||
|
새 scpdb 메서드를 래핑하려면 다음 4 곳을 동기화한다.
|
||||||
|
|
||||||
|
1. `src/stub/java/com/penta/scpdb/ScpDbAgent.java` — 새 시그니처를 추가 (컴파일 통과용)
|
||||||
|
2. `DamoManager.RealBridge` — 실제 호출 메서드 추가
|
||||||
|
3. `DamoManager` 공개 메서드 — `if (REAL_MODE) bridge.xxx(...) else fakeXxx(...)`
|
||||||
|
4. fake 분기 로직 작성 (보통 Base64 또는 JRE 기능)
|
||||||
|
|
||||||
|
> Stub 은 `compileOnly` 로만 사용되므로 산출 jar 에 포함되지 않는다. 운영의 진짜 ScpDbAgent 메서드 시그니처와 stub 시그니처가 다르면 운영에서 `NoSuchMethodError` 가 발생하므로 정확히 일치시켜야 한다.
|
||||||
|
|
||||||
|
## 결과물 사용 방법
|
||||||
|
|
||||||
|
### 권장: 빌드된 jar 직접 참조
|
||||||
|
|
||||||
|
타 Gradle 프로젝트에서는 `damo-manager.jar` 를 lib 폴더에 복사하여 직접 참조하는 방식을 권장한다. (Nexus 배포 없이 즉시 사용 가능)
|
||||||
|
|
||||||
|
**Gradle**:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
dependencies {
|
||||||
|
// 권장. 산출 jar 를 본인 프로젝트의 libs/ 에 복사 후 참조
|
||||||
|
compileOnly files('libs/damo-manager.jar')
|
||||||
|
// 또는 다른 위치를 직접 가리킨다면
|
||||||
|
// compileOnly files('../damo-manager/build/libs/damo-manager.jar')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
WAS lib 폴더에서 클래스를 로드하므로 의존성 scope 는 반드시 **`compileOnly`** (또는 Maven 의 `provided`) 로 둔다. `implementation`/`api` 로 두면 war 에 중복 포함되어 ClassLoader 충돌 위험.
|
||||||
|
|
||||||
|
`api` 로 다른 모듈에 노출이 필요하다면 동일하게 `files(...)` 를 `api` scope 로 (단, 위 충돌 가능성 인지).
|
||||||
|
|
||||||
|
**Maven**:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.eactive.apim.custom.djb</groupId>
|
||||||
|
<artifactId>damo-manager</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<scope>system</scope>
|
||||||
|
<systemPath>${project.basedir}/libs/damo-manager.jar</systemPath>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 사내 Nexus 등에 배포 시 `<scope>provided</scope>`.
|
||||||
|
|
||||||
|
### WAS (Tomcat) 설치
|
||||||
|
|
||||||
|
운영 / 로컬에 따라 lib 폴더 구성이 다르다.
|
||||||
|
|
||||||
|
**운영 (Tomcat)**:
|
||||||
|
|
||||||
|
```
|
||||||
|
$CATALINA_HOME/lib/
|
||||||
|
├── damo-manager.jar
|
||||||
|
└── libs_scpdb-*.jar ← penta scpdb 라이브러리 (실 암복호화)
|
||||||
|
```
|
||||||
|
|
||||||
|
`libs_scpdb-*.jar` 와 함께 네이티브 .so/.dll 및 `/prod/damo/ba_scp/scpdb_agent.ini` 도 준비되어 있어야 한다.
|
||||||
|
|
||||||
|
**로컬 개발**:
|
||||||
|
|
||||||
|
```
|
||||||
|
$CATALINA_HOME/lib/
|
||||||
|
└── damo-manager.jar ← 단독. scpdb 라이브러리 없음
|
||||||
|
```
|
||||||
|
|
||||||
|
WAS 기동 시 콘솔(`catalina.out` 또는 stderr)에 다음과 같은 배너가 출력되면 정상 동작이다.
|
||||||
|
|
||||||
|
```
|
||||||
|
============================================================
|
||||||
|
*** DAMO-MANAGER FAKE MODE ***
|
||||||
|
com.penta.scpdb.ScpDbAgent NOT FOUND on classpath.
|
||||||
|
Fallback:
|
||||||
|
encrypt/decrypt -> Base64 (NO ENCRYPTION)
|
||||||
|
hash -> JRE MessageDigest (SHA-256 / SHA-512)
|
||||||
|
*** DO NOT use this build for production! ***
|
||||||
|
============================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
> Fake 모드는 **암호화가 전혀 없는 단순 Base64 통과** 이므로 운영 절대 금지.
|
||||||
|
|
||||||
|
## 주요 메서드
|
||||||
|
|
||||||
|
```java
|
||||||
|
import com.eactive.apim.custom.djb.damomanager.DamoManager;
|
||||||
|
|
||||||
|
DamoManager damo = new DamoManager(); // 클래스 로딩 시점에 모드 감지
|
||||||
|
|
||||||
|
String cipher = damo.encrypt("hello"); // Base64 cipher text
|
||||||
|
String plain = damo.decrypt(cipher); // → "hello"
|
||||||
|
String h256 = damo.hash(DamoManager.SHA256, "password"); // SHA-256 base64
|
||||||
|
String h512 = damo.hash(DamoManager.SHA512, "password"); // SHA-512 base64
|
||||||
|
|
||||||
|
boolean fake = damo.isFakeMode(); // 디버깅 / 분기용
|
||||||
|
int rc = damo.getReturnCode(); // 0: 성공, -1: 실패
|
||||||
|
```
|
||||||
|
|
||||||
|
| 메서드 | 운영 동작 | Fake 동작 |
|
||||||
|
|---|---|---|
|
||||||
|
| `String encrypt(String plain)` | `ScpEncB64(INI_FILE, "KEY1", plain, "EUC-KR")` | `Base64.encode(plain.getBytes("EUC-KR"))` |
|
||||||
|
| `String decrypt(String b64)` | `ScpDecB64(INI_FILE, "KEY1", b64, "EUC-KR")` | `new String(Base64.decode(b64), "EUC-KR")` |
|
||||||
|
| `String hash(int type, String src)` | `ScpHashB64(type, src, "EUC-KR")` | `MessageDigest(SHA-256/512).digest(src) → Base64` |
|
||||||
|
|
||||||
|
해시 `type` 상수:
|
||||||
|
|
||||||
|
| 상수 | 값 | 알고리즘 |
|
||||||
|
|---|---|---|
|
||||||
|
| `DamoManager.SHA256` | 71 | SHA-256 |
|
||||||
|
| `DamoManager.SHA512` | 73 | SHA-512 |
|
||||||
|
|
||||||
|
기타 유틸 (원본 DamoManager 호환):
|
||||||
|
|
||||||
|
- `Base64Encode(byte[])`, `Base64Decode(String)`
|
||||||
|
- `byteToHex(byte[])`, `byteArrayToHex(byte[])`
|
||||||
|
- `checkHangul(char)`
|
||||||
|
- `getReturnCode()`, `getRevision()`
|
||||||
|
|
||||||
|
## 검증
|
||||||
|
|
||||||
|
스모크 main 이 포함되어 있다.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -cp build/libs/damo-manager.jar com.eactive.apim.custom.djb.damomanager.DamoManager
|
||||||
|
```
|
||||||
|
|
||||||
|
또는:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gradle runFakeSmoke
|
||||||
|
```
|
||||||
|
|
||||||
|
예상 출력:
|
||||||
|
|
||||||
|
```
|
||||||
|
============================================================
|
||||||
|
*** DAMO-MANAGER FAKE MODE ***
|
||||||
|
...
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
revision = 20160503
|
||||||
|
fakeMode = true
|
||||||
|
encrypt = aGVsbG8sIL3M3sCw
|
||||||
|
decrypt = hello, 다모
|
||||||
|
roundtrip = true
|
||||||
|
sha256 b64 = ... (len=44)
|
||||||
|
sha512 b64 = ... (len=88)
|
||||||
|
```
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java-library'
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'com.eactive.apim.custom.djb'
|
||||||
|
version = '1.0.0'
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
stub {
|
||||||
|
java {
|
||||||
|
srcDirs = ['src/stub/java']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// scpdb 가짜 시그니처. 메인 컴파일 통과 전용. 최종 jar 에는 포함되지 않음.
|
||||||
|
compileOnly sourceSets.stub.output
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'damo-manager'
|
||||||
|
archiveVersion = ''
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Implementation-Title' : 'damo-manager',
|
||||||
|
'Implementation-Version': project.version,
|
||||||
|
'Built-By' : 'damo-manager gradle build'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fake 모드 스모크 검증용. 실행: ./gradlew runFakeSmoke
|
||||||
|
tasks.register('runFakeSmoke', JavaExec) {
|
||||||
|
group = 'verification'
|
||||||
|
description = 'Run DamoManager main() with no scpdb on classpath (fake mode smoke test)'
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
|
mainClass = 'com.eactive.apim.custom.djb.damomanager.DamoManager'
|
||||||
|
dependsOn 'classes'
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'damo-manager'
|
||||||
@@ -0,0 +1,363 @@
|
|||||||
|
package com.eactive.apim.custom.djb.damomanager;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 운영(penta scpdb 라이브러리 존재) / 로컬(scpdb 부재) 양쪽에서 동작하는 단일 클래스.
|
||||||
|
*
|
||||||
|
* 클래스패스에 {@code com.penta.scpdb.ScpDbAgent} 가 존재하면 실 호출, 아니면 fake 모드로 자동 fallback.
|
||||||
|
* fake 모드 진입 시 클래스 로딩 시점에 System.err 로 강한 경고 배너 출력.
|
||||||
|
*
|
||||||
|
* fake 모드 동작:
|
||||||
|
* - encrypt(s) : Base64.encode(s.getBytes(EUC-KR)) -- 암호화 없음
|
||||||
|
* - decrypt(s) : new String(Base64.decode(s), EUC-KR)
|
||||||
|
* - hash(t, s) : SHA-256(71) / SHA-512(73) JRE MessageDigest -> Base64
|
||||||
|
*/
|
||||||
|
public class DamoManager {
|
||||||
|
|
||||||
|
public static final int SHA256 = 71;
|
||||||
|
public static final int SHA512 = 73;
|
||||||
|
|
||||||
|
private static final String INI_FILE = "/prod/damo/ba_scp/scpdb_agent.ini";
|
||||||
|
private static final String KEY = "KEY1";
|
||||||
|
private static final String CHARSET = "EUC-KR";
|
||||||
|
|
||||||
|
private static final int SCP_OK = 0;
|
||||||
|
private static final int SCP_FAIL = -1;
|
||||||
|
|
||||||
|
private static final boolean REAL_MODE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
boolean real;
|
||||||
|
try {
|
||||||
|
Class.forName("com.penta.scpdb.ScpDbAgent", false,
|
||||||
|
DamoManager.class.getClassLoader());
|
||||||
|
real = true;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
real = false;
|
||||||
|
printFakeBanner();
|
||||||
|
}
|
||||||
|
REAL_MODE = real;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printFakeBanner() {
|
||||||
|
String line = "============================================================";
|
||||||
|
System.err.println();
|
||||||
|
System.err.println(line);
|
||||||
|
System.err.println(" *** DAMO-MANAGER FAKE MODE ***");
|
||||||
|
System.err.println(" com.penta.scpdb.ScpDbAgent NOT FOUND on classpath.");
|
||||||
|
System.err.println(" Fallback:");
|
||||||
|
System.err.println(" encrypt/decrypt -> Base64 (NO ENCRYPTION)");
|
||||||
|
System.err.println(" hash -> JRE MessageDigest (SHA-256 / SHA-512)");
|
||||||
|
System.err.println(" *** DO NOT use this build for production! ***");
|
||||||
|
System.err.println(line);
|
||||||
|
System.err.println();
|
||||||
|
System.err.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String szRevision = "20160503";
|
||||||
|
private int nReturn;
|
||||||
|
private final RealBridge bridge;
|
||||||
|
|
||||||
|
public DamoManager() {
|
||||||
|
if (REAL_MODE) {
|
||||||
|
this.bridge = new RealBridge();
|
||||||
|
int rc = this.bridge.init();
|
||||||
|
if (rc == 0 || rc == 118) {
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
} else {
|
||||||
|
this.nReturn = rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.bridge = null;
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRevision() {
|
||||||
|
return this.szRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReturnCode() {
|
||||||
|
return this.nReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFakeMode() {
|
||||||
|
return !REAL_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// 운영: ScpEncB64 / ScpDecB64 / ScpHashB64 래핑
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 평문 문자열을 ScpEncB64 로 암호화하여 Base64 cipher text 반환.
|
||||||
|
* fake 모드: 단순 Base64 인코딩.
|
||||||
|
*/
|
||||||
|
public String encrypt(String plain) {
|
||||||
|
if (plain == null) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (REAL_MODE) {
|
||||||
|
try {
|
||||||
|
String out = this.bridge.encB64(plain);
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
return out;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
return Base64.getEncoder().encodeToString(plain.getBytes(CHARSET));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return Base64.getEncoder().encodeToString(plain.getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base64 cipher text 를 ScpDecB64 로 복호화하여 평문 반환.
|
||||||
|
* fake 모드: 단순 Base64 디코딩.
|
||||||
|
*/
|
||||||
|
public String decrypt(String base64Cipher) {
|
||||||
|
if (base64Cipher == null) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (REAL_MODE) {
|
||||||
|
try {
|
||||||
|
String out = this.bridge.decB64(base64Cipher);
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
return out;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] decoded = Base64.getDecoder().decode(base64Cipher);
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
try {
|
||||||
|
return new String(decoded, CHARSET);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
return new String(decoded);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 단방향 해시. type 71 = SHA-256, 73 = SHA-512. 결과는 Base64 문자열.
|
||||||
|
* fake 모드: JRE MessageDigest 사용 (실제 SHA-256/512 결과를 Base64 로 반환).
|
||||||
|
*/
|
||||||
|
public String hash(int type, String src) {
|
||||||
|
if (src == null) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (REAL_MODE) {
|
||||||
|
try {
|
||||||
|
String out = this.bridge.hashB64(type, src);
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
return out;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String algo;
|
||||||
|
if (type == SHA256) {
|
||||||
|
algo = "SHA-256";
|
||||||
|
} else if (type == SHA512) {
|
||||||
|
algo = "SHA-512";
|
||||||
|
} else {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance(algo);
|
||||||
|
byte[] bytes;
|
||||||
|
try {
|
||||||
|
bytes = md.digest(src.getBytes(CHARSET));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
bytes = md.digest(src.getBytes());
|
||||||
|
}
|
||||||
|
this.nReturn = SCP_OK;
|
||||||
|
return Base64.getEncoder().encodeToString(bytes);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
this.nReturn = SCP_FAIL;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Utility (원본 DamoManager 에서 그대로 보존)
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
public String Base64Encode(byte[] var1) {
|
||||||
|
char[] var2 = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
|
||||||
|
StringBuilder var3 = new StringBuilder();
|
||||||
|
int var4 = 0;
|
||||||
|
|
||||||
|
for (int var5 = 0; var5 < var1.length; var5 += 3) {
|
||||||
|
int var6 = (var1[var5] & 255) << 16 & 16777215;
|
||||||
|
if (var5 + 1 < var1.length) {
|
||||||
|
var6 |= (var1[var5 + 1] & 255) << 8;
|
||||||
|
} else {
|
||||||
|
++var4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var5 + 2 < var1.length) {
|
||||||
|
var6 |= var1[var5 + 2] & 255;
|
||||||
|
} else {
|
||||||
|
++var4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int var7 = 0; var7 < 4 - var4; ++var7) {
|
||||||
|
int var8 = (var6 & 16515072) >> 18;
|
||||||
|
var3.append(var2[var8]);
|
||||||
|
var6 <<= 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int var9 = 0; var9 < var4; ++var9) {
|
||||||
|
var3.append("=");
|
||||||
|
}
|
||||||
|
|
||||||
|
return var3.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Base64Decode(String var1) {
|
||||||
|
int[] var2 = new int[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||||
|
byte[] var3 = var1.getBytes();
|
||||||
|
ByteArrayOutputStream var4 = new ByteArrayOutputStream();
|
||||||
|
int var5 = 0;
|
||||||
|
|
||||||
|
while (var5 < var3.length) {
|
||||||
|
int var6 = 0;
|
||||||
|
if (var2[var3[var5]] != -1) {
|
||||||
|
var6 = (var2[var3[var5]] & 255) << 18;
|
||||||
|
int var7 = 0;
|
||||||
|
if (var5 + 1 < var3.length && var2[var3[var5 + 1]] != -1) {
|
||||||
|
var6 |= (var2[var3[var5 + 1]] & 255) << 12;
|
||||||
|
++var7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var5 + 2 < var3.length && var2[var3[var5 + 2]] != -1) {
|
||||||
|
var6 |= (var2[var3[var5 + 2]] & 255) << 6;
|
||||||
|
++var7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var5 + 3 < var3.length && var2[var3[var5 + 3]] != -1) {
|
||||||
|
var6 |= var2[var3[var5 + 3]] & 255;
|
||||||
|
++var7;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (var7 > 0) {
|
||||||
|
int var8 = (var6 & 16711680) >> 16;
|
||||||
|
var4.write((char) var8);
|
||||||
|
var6 <<= 8;
|
||||||
|
--var7;
|
||||||
|
}
|
||||||
|
|
||||||
|
var5 += 4;
|
||||||
|
} else {
|
||||||
|
++var5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return var4.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String byteToHex(byte[] var1) {
|
||||||
|
String var2 = "";
|
||||||
|
String var3 = "";
|
||||||
|
|
||||||
|
for (int var4 = 0; var4 < var1.length; ++var4) {
|
||||||
|
var3 = Integer.toHexString(var1[var4]);
|
||||||
|
if (var3.length() >= 2) {
|
||||||
|
var3 = var3.substring(var3.length() - 2);
|
||||||
|
} else {
|
||||||
|
for (int var5 = 0; var5 < 2 - var3.length(); ++var5) {
|
||||||
|
var3 = "0" + var3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var2 = var2 + " " + var3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var2.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String byteArrayToHex(byte[] var1) {
|
||||||
|
StringBuilder var2 = new StringBuilder();
|
||||||
|
|
||||||
|
for (byte var6 : var1) {
|
||||||
|
var2.append(String.format("%02x ", var6 & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
return var2.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkHangul(char var1) {
|
||||||
|
return var1 >= '가' && var1 <= '힣';
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// 운영 ScpDbAgent 호출 격리. REAL_MODE == true 일 때만 인스턴스화되어
|
||||||
|
// ScpDbAgent 심볼이 JVM 에 resolve 된다. fake 모드에서는 이 클래스 자체가
|
||||||
|
// 로딩되지 않으므로 NoClassDefFoundError 가 발생하지 않는다.
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
private static final class RealBridge {
|
||||||
|
private final com.penta.scpdb.ScpDbAgent agt = new com.penta.scpdb.ScpDbAgent();
|
||||||
|
|
||||||
|
int init() {
|
||||||
|
return agt.AgentInit(INI_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
String encB64(String src) {
|
||||||
|
return agt.ScpEncB64(INI_FILE, KEY, src, CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
String decB64(String src) {
|
||||||
|
return agt.ScpDecB64(INI_FILE, KEY, src, CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
String hashB64(int type, String src) {
|
||||||
|
return agt.ScpHashB64(type, src, CHARSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Smoke test 용 main. 운영 코드에서는 호출되지 않음.
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DamoManager m = new DamoManager();
|
||||||
|
System.out.println("revision = " + m.getRevision());
|
||||||
|
System.out.println("fakeMode = " + m.isFakeMode());
|
||||||
|
|
||||||
|
String plain = "hello, 다모";
|
||||||
|
String enc = m.encrypt(plain);
|
||||||
|
String dec = m.decrypt(enc);
|
||||||
|
System.out.println("encrypt = " + enc);
|
||||||
|
System.out.println("decrypt = " + dec);
|
||||||
|
System.out.println("roundtrip = " + plain.equals(dec));
|
||||||
|
|
||||||
|
String h256 = m.hash(SHA256, plain);
|
||||||
|
String h512 = m.hash(SHA512, plain);
|
||||||
|
System.out.println("sha256 b64 = " + h256 + " (len=" + h256.length() + ")");
|
||||||
|
System.out.println("sha512 b64 = " + h512 + " (len=" + h512.length() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.penta.scpdb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub. DamoManager 컴파일 통과 전용으로, 운영에서는 실제 penta scpdb 라이브러리의 동일 FQCN 클래스가 사용된다.
|
||||||
|
* 본 stub 은 산출 jar 에 포함되지 않는다 (build.gradle 의 compileOnly).
|
||||||
|
*
|
||||||
|
* DamoManager 가 호출하는 시그니처만 노출한다.
|
||||||
|
*/
|
||||||
|
public class ScpDbAgent {
|
||||||
|
|
||||||
|
public ScpDbAgent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int AgentInit(String iniFile) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String ScpEncB64(String iniFile, String key, String src, String charset) throws ScpDbAgentException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String ScpDecB64(String iniFile, String key, String src, String charset) throws ScpDbAgentException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String ScpHashB64(int type, String src, String charset) throws ScpDbAgentException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.penta.scpdb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub. 운영 환경에서는 실제 penta scpdb 라이브러리의 동일 클래스로 대체된다.
|
||||||
|
* 본 stub 은 컴파일 통과 전용이며 산출 jar 에는 포함되지 않는다.
|
||||||
|
*/
|
||||||
|
public class ScpDbAgentException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private int returnedValue;
|
||||||
|
|
||||||
|
public ScpDbAgentException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScpDbAgentException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScpDbAgentException(String message, int returnedValue) {
|
||||||
|
super(message);
|
||||||
|
this.returnedValue = returnedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int returnedValue() {
|
||||||
|
return returnedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user