react-native-c-shield
v1.0.0
Published
C-Shield SDK by CMC Cyber Security protects React Native apps with RASP, SSL certificate pinning, and API integrity protection (AIP).
Maintainers
Readme
react-native-c-shield
C-Shield SDK của CMC Cyber Security bảo vệ ứng dụng React Native bằng RASP, SSL certificate pinning và bảo vệ tính toàn vẹn API (AIP).
Cài đặt
npm install react-native-c-shield axiosTích hợp vào host app
C-Shield native SDK được CMC CS cung cấp riêng theo bundle/application ID và signing certificate của từng ứng dụng. Hãy dùng đúng AAR/XCFramework được cấp cho host app.
Android
Đặt hai AAR do CMC CS cung cấp vào
android/app/libs/:android/app/libs/ ├── cshield-sdk-debug.aar └── cshield-sdk-release.aarKhai báo binary và các transitive dependency bắt buộc trong
android/app/build.gradle:dependencies { debugImplementation(files("libs/cshield-sdk-debug.aar")) releaseImplementation(files("libs/cshield-sdk-release.aar")) // File AAR cục bộ không tự khai báo transitive dependencies. implementation("com.squareup.okhttp3:okhttp:4.11.0") implementation("com.squareup.retrofit2:converter-gson:2.11.0") }Clean và build lại Android để React Native sinh native Codegen artifacts:
cd android ./gradlew clean cd .. npx react-native run-android
iOS
- Đặt các framework do CMC cung cấp trong thư mục
ios/Libs/:
Dùng Xcode mở thư mục ios của dự án theo đường dẫn <your_app>/ios/YourApp.xcworkspace. Tạo thư mục Libs trong <your_app>/ios/, rồi tạo tiếp các thư mục con Debug và Release trong Libs:
<your_app>/ios/
├── Libs/
│ ├── OpenSSL.xcframework
│ ├── Debug/
│ │ └── CShieldSDK.xcframework
│ └── Release/
│ └── CShieldSDK.xcframework
├── Podfile
└── YourApp.xcworkspaceLưu ý:
CShieldSDK-Debug.xcframeworkphải được đổi tên thànhCShieldSDK.xcframeworkkhi đặt vào thư mụcDebug/.
Lưu ý: Phải kéo thả từng file
.xcframeworkvào đúng vị trí tương ứng trong Xcode Project Navigator:
OpenSSL.xcframework→ kéo vào nhómLibs/
CShieldSDK.xcframework(Debug) → kéo vào nhómLibs/Debug/
CShieldSDK.xcframework(Release) → kéo vào nhómLibs/Release/Nếu không kéo thả, Xcode sẽ không nhận ra các framework này trong project.
Cập nhật
post_installtrongios/Podfileđể pod React Native wrapper và app target tìm đúng framework theo configuration và SDK slice.target 'YourApp' do config = use_native_modules! post_install do |installer| react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false ) installer.pods_project.targets.each do |target| next unless target.name == 'CShieldSDK' target.build_configurations.each do |build_config| variant = build_config.name.include?('Release') ? 'Release' : 'Debug' device_paths = [ '$(inherited)', "\"$(PODS_ROOT)/../Libs/#{variant}/CShieldSDK.xcframework/ios-arm64\"", '"$(PODS_ROOT)/../Libs/OpenSSL.xcframework/ios-arm64"', ] simulator_paths = [ '$(inherited)', "\"$(PODS_ROOT)/../Libs/#{variant}/CShieldSDK.xcframework/ios-arm64_x86_64-simulator\"", '"$(PODS_ROOT)/../Libs/OpenSSL.xcframework/ios-arm64_x86_64-simulator"', ] build_config.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]'] = device_paths build_config.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]'] = simulator_paths end end installer.aggregate_targets.each do |aggregate_target| aggregate_target.xcconfigs.each do |config_name, xcconfig| variant = config_name.to_s.include?('Release') ? 'Release' : 'Debug' path = aggregate_target.xcconfig_path(config_name).to_s xcconfig.save_as(aggregate_target.xcconfig_path(config_name)) File.open(path, 'a') do |file| file.puts %(FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) "$(PODS_ROOT)/../Libs/#{variant}/CShieldSDK.xcframework/ios-arm64" "$(PODS_ROOT)/../Libs/OpenSSL.xcframework/ios-arm64") file.puts %(FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "$(PODS_ROOT)/../Libs/#{variant}/CShieldSDK.xcframework/ios-arm64_x86_64-simulator" "$(PODS_ROOT)/../Libs/OpenSSL.xcframework/ios-arm64_x86_64-simulator") end end end end endEmbed OpenSSL
<YourApp> target → General → Frameworks, Libraries, and Embedded Content → +
Chọn Libs/OpenSSL.xcframework, cột Embed đặt thành Embed & Sign.
Nếu thấy CShieldSDK.xcframework, chọn framework rồi xoá bằng dấu -.
<YourApp> target → Build Settings → User Script Sandboxing → NoThêm Run Script Phase để embed CShieldSDK
<YourApp> target → Build Phases → + → New Run Script Phase
Đặt tên phase là Embed CShieldSDK, kéo lên ngay bên dưới Compile Sources.
Dán script sau vào ô script:
set -e
if [[ "$SDK_NAME" == *"simulator"* ]]; then
SLICE="ios-arm64_x86_64-simulator"
else
SLICE="ios-arm64"
fi
if [[ "$CONFIGURATION" == *"Release"* ]] || \
[[ "$CONFIGURATION" == *"Profile"* ]]; then
LIB_CONFIG="Release"
else
LIB_CONFIG="Debug"
fi
SRC="${PROJECT_DIR}/Libs/${LIB_CONFIG}/CShieldSDK.xcframework/${SLICE}/CShieldSDK.framework"
DEST="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/CShieldSDK.framework"
if [[ ! -d "$SRC" ]]; then
echo "error: Missing C-Shield framework at $SRC" >&2
exit 1
fi
mkdir -p "$DEST"
/usr/bin/rsync -a --delete "${SRC}/" "${DEST}/"
if [[ -n "${EXPANDED_CODE_SIGN_IDENTITY}" ]]; then
/usr/bin/codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" "$DEST"
fiThêm Output File cho phase:
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/CShieldSDK.frameworkCài lại Pods:
pod install
Sử dụng
Khởi tạo C-Shield trước khi sử dụng RASP, SSL pinning hoặc AIP. Native SDK được cung cấp riêng theo bundle/application ID và signing certificate của host app, vì vậy hãy sử dụng đúng AAR/XCFramework được cấp cho ứng dụng đó.
import CShield from 'react-native-c-shield';
await CShield.initialize({});RASP
Tạo checker với các cơ chế bảo vệ mà host app cần, cấu hình cách xử lý khi phát hiện mối đe dọa và đăng ký nhận kết quả liên tục. Luôn hủy subscription và giải phóng checker khi không còn sử dụng.
import { useEffect } from 'react';
import CShield, {
type RaspEventPayload,
type ThreatEventPayload,
} from 'react-native-c-shield';
async function startRaspGuard(): Promise<() => void> {
const subscriptionId = `rasp-main-${Date.now()}`;
let checkerId: string | undefined;
const loadThreatSubscription = CShield.onThreatEvent(
(event: ThreatEventPayload) => {
console.warn('Phát hiện mối đe dọa khi khởi động:', event.threatType);
}
);
const raspEventSubscription = CShield.onRaspEvent(
(event: RaspEventPayload) => {
if (event.subscriptionId !== subscriptionId) return;
if (event.type === 'result' && event.vulnerable) {
console.warn('Phát hiện mối đe dọa RASP:', {
checkType: event.checkType,
threatAction: event.threatAction,
});
} else if (event.type === 'error') {
console.error(event.errorCode, event.errorMessage);
}
}
);
try {
await CShield.initialize({});
checkerId = await CShield.raspBuild({
checkDebugger: true,
rootDetector: true,
tampering: true,
emulator: true,
deviceSecurityState: true,
});
await CShield.raspSetConfig(checkerId, {
trustedStores: [],
threatActionConfig: {
debuggerDetectedAction: 'NotifyApp',
rootDetectedAction: 'NotifyApp',
tamperingDetectedAction: 'NotifyApp',
emulatorDetectedAction: 'NotifyApp',
deviceSecurityStateUnsafeDetectedAction: 'NotifyApp',
},
});
const quickResult = await CShield.raspQuickCheck(checkerId);
console.log('Kết quả kiểm tra nhanh RASP:', quickResult);
await CShield.raspSubscribe(checkerId, subscriptionId, true, true);
} catch (error) {
loadThreatSubscription.remove();
raspEventSubscription.remove();
if (checkerId) await CShield.raspDispose(checkerId).catch(() => {});
throw error;
}
return () => {
loadThreatSubscription.remove();
raspEventSubscription.remove();
void CShield.raspCancelSubscribe(subscriptionId).catch(() => {});
if (checkerId) void CShield.raspDispose(checkerId).catch(() => {});
};
}
export default function App() {
useEffect(() => {
let disposed = false;
let stop: (() => void) | undefined;
void startRaspGuard()
.then((cleanup) => {
if (disposed) cleanup();
else stop = cleanup;
})
.catch(console.error);
return () => {
disposed = true;
stop?.();
};
}, []);
// ...
}NotifyApp gửi thông tin mối đe dọa về JavaScript mà không kết thúc ứng dụng.
Hãy chọn cách phản ứng phù hợp với chính sách bảo mật của host app.
SSL pinning và AIP
Cấu hình SPKI pin và hostname trước khi gửi các request được bảo vệ:
import CShield from 'react-native-c-shield';
await CShield.initialize({});
await CShield.sslConfigure(['sha256/<base64-spki-pin>'], 'api.example.com');Axios
Sử dụng một Axios instance riêng cho host cần bảo vệ. Adapter chuyển các HTTPS request qua native transport có pinning, còn interceptor ký request và xác minh chữ ký response bằng AIP.
import axios from 'axios';
import CShield, {
attachCShieldAxiosInterceptors,
createCShieldAxiosAdapter,
} from 'react-native-c-shield';
await CShield.initialize({});
await CShield.sslConfigure(['sha256/<base64-spki-pin>'], 'api.example.com');
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 15_000,
adapter: createCShieldAxiosAdapter({ hostname: 'api.example.com' }),
});
const detachCShield = attachCShieldAxiosInterceptors(api);
const response = await api.post('/session', { username: 'demo' });
// Gọi khi Axios instance không còn được sử dụng.
detachCShield();Native adapter hỗ trợ request body dạng chuỗi, ArrayBuffer và typed array.
Adapter không hỗ trợ body dạng Multipart/FormData.
Request cấp thấp
Sử dụng CShieldSSL.requestJson khi host app không cần Axios. API này ký request,
gửi request qua native transport có pinning và xác minh response trước khi trả
về dữ liệu JSON đã parse.
import CShield, { CShieldSSL } from 'react-native-c-shield';
await CShield.initialize({});
await CShield.sslConfigure(['sha256/<base64-spki-pin>'], 'api.example.com');
const response = await CShieldSSL.requestJson<{ token: string }>({
method: 'POST',
url: 'https://api.example.com/session',
json: { username: 'demo' },
});
console.log(response.data?.token);Để gửi và nhận dữ liệu byte thô, sử dụng CShieldSSL.request:
const response = await CShieldSSL.request({
method: 'GET',
url: 'https://api.example.com/profile',
});
console.log(response.statusCode, response.text);