Hi,
I went through the Android developers tutorial for RenderScript (allows to compute on GPU using C99 and java). I took the code out of the samples and I have a problem with a non recognized function:
In HelloCompute.java main class there is this line:
Code:
mScript.forEach_root()
Eclipse can't find the forEach_root() function.
I looked into the generated java class of the C part, which should be called by the forEach_root() java call:
Code:
package com.example.android.rs.hellocompute;
import android.renderscript.*;
import android.content.res.Resources;
/**
* @hide
*/
public class ScriptC_mono extends ScriptC {
private static final String __rs_resource_name = "mono";
// Constructor
public ScriptC_mono(RenderScript rs) {
this(rs,
rs.getApplicationContext().getResources(),
rs.getApplicationContext().getResources().getIdentifier(
__rs_resource_name, "raw",
rs.getApplicationContext().getPackageName()));
}
public ScriptC_mono(RenderScript rs, Resources resources, int id) {
super(rs, resources, id);
__U8_4 = Element.U8_4(rs);
}
private Element __U8_4;
}
An Idea anyone?
Thanks,
DP
darkPrint said:
Hi,
I went through the Android developers tutorial for RenderScript (allows to compute on GPU using C99 and java). I took the code out of the samples and I have a problem with a non recognized function:
In HelloCompute.java main class there is this line:
Code:
mScript.forEach_root()
Eclipse can't find the forEach_root() function.
I looked into the generated java class of the C part, which should be called by the forEach_root() java call:
Code:
package com.example.android.rs.hellocompute;
import android.renderscript.*;
import android.content.res.Resources;
/**
* @hide
*/
public class ScriptC_mono extends ScriptC {
private static final String __rs_resource_name = "mono";
// Constructor
public ScriptC_mono(RenderScript rs) {
this(rs,
rs.getApplicationContext().getResources(),
rs.getApplicationContext().getResources().getIdentifier(
__rs_resource_name, "raw",
rs.getApplicationContext().getPackageName()));
}
public ScriptC_mono(RenderScript rs, Resources resources, int id) {
super(rs, resources, id);
__U8_4 = Element.U8_4(rs);
}
private Element __U8_4;
}
An Idea anyone?
Thanks,
DP
Click to expand...
Click to collapse
Okay, it was just a corrupted project issue. Loosing so much time for such a stupid issue...
Well, know you know, if you get to this error, clean the project and rebuid, that's it.
Cheers,
DP
I'm trying to build CarbonRom for my phone, and when its compiling i get these errors. I'm using java version 1.7 and i'm running Ubuntu 14.04
Code:
target Java: Camera2 (/home/seyi/carbon/out/target/common/obj/APPS/Camera2_intermediates/classes)
target Static Jar: android-opt-datetimepicker (/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/android-opt-datetimepicker_intermediates/javalib.jar)
ProGuard, version 4.4
Reading program jar [/home/seyi/carbon/out/target/common/obj/APPS/DocumentsUI_intermediates/classes.jar]
Reading library jar [/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar]
Reading library jar [/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/core-junit_intermediates/classes.jar]
Reading library jar [/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar]
Reading library jar [/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar]
Reading library jar [/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/framework2_intermediates/classes.jar]
Note: com.google.common.base.FinalizableReferenceQueue accesses a method 'startFinalizer(java.lang.Class,java.lang.Object)' dynamically
Note: android.support.v4.text.ICUCompatIcs accesses a method 'getScript(java.lang.String)' dynamically
Maybe this is program method 'android.support.v4.text.ICUCompat { java.lang.String getScript(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImpl { java.lang.String getScript(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImplBase { java.lang.String getScript(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImplIcs { java.lang.String getScript(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompatIcs { java.lang.String getScript(java.lang.String); }'
Maybe this is library method 'libcore.icu.ICU { java.lang.String getScript(java.lang.String); }'
Note: android.support.v4.text.ICUCompatIcs accesses a method 'addLikelySubtags(java.lang.String)' dynamically
Maybe this is program method 'android.support.v4.text.ICUCompat { java.lang.String addLikelySubtags(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImpl { java.lang.String addLikelySubtags(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImplBase { java.lang.String addLikelySubtags(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompat$ICUCompatImplIcs { java.lang.String addLikelySubtags(java.lang.String); }'
Maybe this is program method 'android.support.v4.text.ICUCompatIcs { java.lang.String addLikelySubtags(java.lang.String); }'
Maybe this is library method 'libcore.icu.ICU { java.lang.String addLikelySubtags(java.lang.String); }'
Note: com.google.common.base.internal.Finalizer accesses a method 'finalizeReferent()' dynamically
Maybe this is program method 'com.google.common.base.FinalizableReference { void finalizeReferent(); }'
Note: the configuration keeps the entry point 'com.google.common.cache.LocalCache { com.google.common.cache.LocalCache$ReferenceEntry newEntry(java.lang.Object,int,com.google.common.cache.LocalCache$ReferenceEntry); }', but not the descriptor class 'com.google.common.cache.LocalCache$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.cache.LocalCache { com.google.common.cache.LocalCache$ReferenceEntry copyEntry(com.google.common.cache.LocalCache$ReferenceEntry,com.google.common.cache.LocalCache$ReferenceEntry); }', but not the descriptor class 'com.google.common.cache.LocalCache$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.cache.LocalCache { com.google.common.cache.LocalCache$ReferenceEntry copyEntry(com.google.common.cache.LocalCache$ReferenceEntry,com.google.common.cache.LocalCache$ReferenceEntry); }', but not the descriptor class 'com.google.common.cache.LocalCache$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.cache.LocalCache { com.google.common.cache.LocalCache$ValueReference newValueReference(com.google.common.cache.LocalCache$ReferenceEntry,java.lang.Object,int); }', but not the descriptor class 'com.google.common.cache.LocalCache$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.collect.MapMakerInternalMap { com.google.common.collect.MapMakerInternalMap$ReferenceEntry newEntry(java.lang.Object,int,com.google.common.collect.MapMakerInternalMap$ReferenceEntry); }', but not the descriptor class 'com.google.common.collect.MapMakerInternalMap$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.collect.MapMakerInternalMap { com.google.common.collect.MapMakerInternalMap$ReferenceEntry copyEntry(com.google.common.collect.MapMakerInternalMap$ReferenceEntry,com.google.common.collect.MapMakerInternalMap$ReferenceEntry); }', but not the descriptor class 'com.google.common.collect.MapMakerInternalMap$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.collect.MapMakerInternalMap { com.google.common.collect.MapMakerInternalMap$ReferenceEntry copyEntry(com.google.common.collect.MapMakerInternalMap$ReferenceEntry,com.google.common.collect.MapMakerInternalMap$ReferenceEntry); }', but not the descriptor class 'com.google.common.collect.MapMakerInternalMap$ReferenceEntry'
Note: the configuration keeps the entry point 'com.google.common.collect.MapMakerInternalMap { com.google.common.collect.MapMakerInternalMap$ValueReference newValueReference(com.google.common.collect.MapMakerInternalMap$ReferenceEntry,java.lang.Object); }', but not the descriptor class 'com.google.common.collect.MapMakerInternalMap$ReferenceEntry'
Note: there were 8 unkept descriptor classes in kept class members.
You should consider explicitly keeping the mentioned classes
(using '-keep').
Note: there were 4 accesses to class members by means of introspection.
You should consider explicitly keeping the mentioned class members
(using '-keep' or '-keepclassmembers').
Preparing output jar [/home/seyi/carbon/out/target/common/obj/APPS/DocumentsUI_intermediates/proguard.classes.jar]
Copying resources from program jar [/home/seyi/carbon/out/target/common/obj/APPS/DocumentsUI_intermediates/classes.jar]
target Java: com.android.emailsync (/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/com.android.emailsync_intermediates/classes)
target Static Jar: android-common-chips (/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/android-common-chips_intermediates/javalib.jar)
target Static Jar: libphotoviewer (/home/seyi/carbon/out/target/common/obj/JAVA_LIBRARIES/libphotoviewer_intermediates/javalib.jar)
target Java: Gallery2 (/home/seyi/carbon/out/target/common/obj/APPS/Gallery2_intermediates/classes)
target Dex: LatinIME
target Java: Launcher3 (/home/seyi/carbon/out/target/common/obj/APPS/Launcher3_intermediates/classes)
target Dex: PackageInstaller
target Java: Contacts (/home/seyi/carbon/out/target/common/obj/APPS/Contacts_intermediates/classes)
target Java: Dialer (/home/seyi/carbon/out/target/common/obj/APPS/Dialer_intermediates/classes)
target Java: Mms (/home/seyi/carbon/out/target/common/obj/APPS/Mms_intermediates/classes)
target Java: Settings (/home/seyi/carbon/out/target/common/obj/APPS/Settings_intermediates/classes)
[COLOR="Red"]packages/apps/Settings/src/com/android/settings/profiles/ProfileAirplaneModePreference.java:42: error: cannot find symbol
private ProfileConfig.AirplaneModeItem mAirplaneModeItem;
^
symbol: class AirplaneModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileAirplaneModePreference.java:105: error: cannot find symbol
public void setAirplaneModeItem(ProfileConfig.AirplaneModeItem airplaneModeItem) {
^
symbol: class AirplaneModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileAirplaneModePreference.java:155: error: cannot find symbol
public ProfileConfig.AirplaneModeItem getAirplaneModeItem() {
^
symbol: class AirplaneModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileRingModePreference.java:42: error: cannot find symbol
private ProfileConfig.RingModeItem mRingModeItem;
^
symbol: class RingModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileRingModePreference.java:105: error: cannot find symbol
public void setRingModeItem(ProfileConfig.RingModeItem ringModeItem) {
^
symbol: class RingModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileRingModePreference.java:159: error: cannot find symbol
public ProfileConfig.RingModeItem getRingModeItem() {
^
symbol: class RingModeItem
location: class ProfileConfig
packages/apps/Settings/src/com/android/settings/profiles/ProfileConnectionPreference.java:126: error: cannot find symbol
final String[] connectionNames = getContext().getResources().getStringArray(mConnectionItem.mChoices);
^
symbol: variable mChoices
location: variable mConnectionItem of type ConnectionItem
packages/apps/Settings/src/com/android/settings/profiles/ProfileConnectionPreference.java:131: error: cannot find symbol
builder.setSingleChoiceItems(mConnectionItem.mChoices, currentChoice, new DialogInterface.OnClickListener() {
^
symbol: variable mChoices
location: variable mConnectionItem of type ConnectionItem
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
8 errors[/COLOR]
Overview
In the previous post, we learned how to integrate the UserDetect API in Safety Detect into your app to identify fake users. I've been glad to receive so much positive feedback. In this post, I'll introduce SysIntegrity (system integrity check), yet another handy function in Safety Detect. Apps can face malicious attacks when they run on insecure devices, for example, rooted devices. For certain apps, such as e-commerce apps, ensuring a secure running environment during user transactions is particularly crucial. SysIntegrity enables apps to do so by helping detect device system-related risks in advance.
I encountered this function on the HUAWEI Developers website. SysIntegrity works by integrating the Safety Detect SDK into your app, and calling the SysIntegrity API in Safety Detect. It performs the check within a Trusted Execution Environment (TEE) and signs the check result with an X.509 digital certificate to ensure that it is trustworthy and tamperproof.
Now let's take a look at what it's like in practice.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Next, I'll show you how to integrate SysIntegrity.
Content
1 Preparations
1.1 Installing Android studio
1.2 Configuring App Information in AppGallery Connect
1.3 Configuring the Huawei Maven Repository Address
1.4 Adding Build Dependencies
1.5 Configuring Obfuscation Scripts
2 Code Development
2.1 Creating a SafetyDetectClient Instance and Generating a Nonce
2.2 Calling the SysIntegrity API
2.3 Verifying the Check Result on the App Server
2.4 Obtaining the System Integrity Check Result
1. Preparations
1.1 Installing Android Studio
To install Android Studio, please refer to the following:
l Android Studio Official Website
l Android Studio Installation and Configuration
1.2 Configuring App Information in AppGallery Connect
Before developing an app, you'll need to configure the app information in AppGallery Connect. For more details, please refer to Preparations.
1.3 Configuring the Huawei Maven Repository Address
Open the build.gradle file in the root directory of your Android Studio project.
Add the AppGallery Connect plug-in and the Maven repository address.
(1) Go to buildscript > repositories and configure the Maven repository address for the HMS Core SDK.
(2) Go to allprojects > repositories and configure the Maven repository address for the HMS Core SDK.
(3) If the agconnect-services.json file has been added to the app, go to buildscript > dependencies and add the AppGallery Connect plug-in configuration.
XML:
<p style="line-height: 1.5em;">apply plugin: 'com.huawei.agconnect'
</p>
Add the build dependency in the dependencies section.
XML:
<p style="line-height: 1.5em;">dependencies {
implementation 'com.huawei.hms:safetydetect:5.0.5.302'
}
</p>
1.5 Configuring Obfuscation Scripts
If you are using AndResGuard, add its trustlist to the build.gradle file in the app directory of your project. For more details about the code, please refer to Configuring Obfuscation Scripts on the HUAWEI Developers website.
2. Code Development
2.1 Creating a SafetyDetectClient Instance and Generating a Nonce
The nonce value will be contained in the check result. You can check the nonce value to verify that the returned result corresponds to your request, and does not encounter replay attacks. A nonce value should:
l Be used only once.
l Contain 16 to 66 bytes.
l Be derived from data sent to your server (Recommended).
2.2 Calling the SysIntegrity API
(1) The SysIntegrity API has two input parameters: the nonce value (obtained during the previous step) and your app ID. You can obtain the app ID from the agconnect-services.jsonfile under the app directory of your project.
Ø Sign in to AppGallery Connect and click My projects.
Ø Find your app project and click the desired app name.
Ø Go to Project Setting > General information, and view the app ID in the App information area.
Java:
<p style="line-height: 1.5em;">private void onAdapterItemClick(int position) {
// Call the SysIntegrity API to check for risks in the payment environment.
SafetyDetectUtil.detectSysIntegrity(this, new ICallBack<Boolean>() {
@Override
public void onSuccess(Boolean baseIntegrity) {
if (baseIntegrity) {
// The system integrity is not corrupted, and the user can proceed with the purchase.
buy(productInfo);
} else {
// The system integrity is corrupted. A popup is displayed to warn the user and ask the user whether to continue.
showRootTipDialog(productInfo);
}
}
…
});
}
</p>
(3) In my app, I encapsulated the SysIntegrity API in the detectSysIntegrity method of the SafetyDetectUtil.java class. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">public static void detectSysIntegrity(final Activity activity, final ICallBack<? super Boolean> callBack) {
// Generate a nonce value.
byte[] nonce = ("Sample" + System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8);
// Read the app_id field from the agconnect-services.json file in the app directory.
String appId = AGConnectServicesConfig.fromContext(activity).getString("client/app_id");
// Obtain the Safety Detect client, call the SysIntegrity API, and add a success event listener.
SysIntegrityRequest sysintegrityrequest = new SysIntegrityRequest();
sysintegrityrequest.setAppid(appId);
sysintegrityrequest.setNonce(nonce);
// PS256 or RS256
sysintegrityrequest.setAlg("RS256");
Task task = mClient.sysIntegrity(sysintegrityrequest);
task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() {
@Override
public void onSuccess(SysIntegrityResp response) {
// Call the getResult method of the SysIntegrityResp class to obtain the check result.
String jwsStr = response.getResult();
VerifyResultHandler verifyResultHandler = new VerifyResultHandler(jwsStr, callBack);
// Send the check result to your server for verification.
verifyJws(activity, jwsStr, verifyResultHandler);
}
});
}
</p>
(4) Here, I called the relevant app server API in the verifyJws method to verify the check result. The third parameter in this method is an object of the VerifyResultHandler class, which implements a callback API to process the verification result.
2.3 Verifying the Check Result on the App Server
After receiving the check result from the TSMS server, the app will send the result to the app server. The server uses the HUAWEI CBG Root CA certificate to verify the signature and certificate chain in the check result, and thereby determines whether the check result is valid.
The sample code for the app server to read the certificate and verify the JWS string is as follows:
(1) Parse the header, payload, and signature from the JWS string.
Java:
<p style="line-height: 1.5em;">public JwsVerifyResp verifyJws(JwsVerifyReq jwsVerifyReq) {
// Obtain the JWS information sent from the app to the server.
String jwsStr = jwsVerifyReq.getJws();
// Parse the JWS segments. A JWS has three fixed segments, which are separated by periods (.).
String[] jwsSplit = jwsStr.split("\\.");
try {
// Perform Base64 decoding on each segment and construct a JWS object for each decoded segment.
JWSObject jwsObject = new JWSObject(new Base64URL(jwsSplit[0]), new Base64URL(jwsSplit[1]), new Base64URL(jwsSplit[2]));
// Verify the JWS and set the verification result.
boolean result = VerifySignatureUtil.verifySignature(jwsObject);
// Construct the response body for check result verification on the app server.
JwsVerifyResp jwsVerifyResp = new JwsVerifyResp();
jwsVerifyResp.setResult(result);
} catch (ParseException | NoSuchAlgorithmException e) {
RUN_LOG.catching(e);
}
return jwsVerifyResp;
}
</p>
(2) Use the verifySignature method of the VerifySignatureUtil class to verify relevant information, including the JWS signature algorithm, certificate chain, host name in signing certificate, and JWS signature. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">public static boolean verifySignature(JWSObject jws) throws NoSuchAlgorithmException {
JWSAlgorithm jwsAlgorithm = jws.getHeader().getAlgorithm();
// 1. Verify the JWS signature algorithm.
if ("RS256".equals(jwsAlgorithm.getName())) {
// Verify the certificate chain and obtain an instance of the Signature class based on the signature algorithm to verify the signature.
return verify(Signature.getInstance("SHA256withRSA"), jws);
}
return false;
}
private static boolean verify(Signature signature, JWSObject jws) {
// Extract the certificate chain information from the JWS header and convert the certificate chain into a proper type for subsequent processing.
X509Certificate[] certs = extractX509CertChain(jws);
// 2. Verify the certificate chain.
try {
verifyCertChain(certs);
} catch (Exception e) {
return false;
}
// 3. Verify the domain name in the signing certificate (leaf certificate). The domain name must be sysintegrity.platform.hicloud.com.
try {
new DefaultHostnameVerifier().verify("sysintegrity.platform.hicloud.com", certs[0]);
} catch (SSLException e) {
return false;
}
// 4. Verify the JWS signature information using the public key obtained from the signing certificate.
PublicKey pubKey = certs[0].getPublicKey();
try {
// Use the public key obtained from the signing certificate to initialize the Signature instance.
signature.initVerify(pubKey);
// Extract the input signature from the JWS and pass it to the Signature instance.
signature.update(jws.getSigningInput());
// Use the Signature instance to verify the signature information.
return signature.verify(jws.getSignature().decode());
} catch (InvalidKeyException | SignatureException e) {
return false;
}
}
</p>
(3) Call the extractX509CertChain method to extract the certificate chain from the JWS header. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">private static X509Certificate[] extractX509CertChain(JWSObject jws) {
List<X509Certificate> certs = new ArrayList<>();
List<com.nimbusds.jose.util.Base64> x509CertChain = jws.getHeader().getX509CertChain();
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
certs.addAll(x509CertChain.stream().map(cert -> {
try {
return (X509Certificate) certFactory.generateCertificate( new ByteArrayInputStream(cert.decode()) );
} catch (CertificateException e) {
RUN_LOG.error("X5c extract failed!");
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toList()));
} catch (CertificateException e) {
RUN_LOG.error("X5c extract failed!");
}
return (X509Certificate[]) certs.toArray();
}
</p>
(4) Call the verifyCertChain method to verify the certificate chain. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">private static void verifyCertChain(X509Certificate[] certs) throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException {
// Verify the validity period and issuing relationship of each certificate one by one.
for (int i = 0; i < certs.length - 1; ++i) {
certs[i].checkValidity();
PublicKey pubKey = certs[i + 1].getPublicKey();
certs[i].verify(pubKey);
}
// Use the preset HUAWEI CBG Root CA certificate to verify the last certificate in the certificate chain.
PublicKey caPubKey = huaweiCbgRootCaCert.getPublicKey();
certs[certs.length - 1].verify(caPubKey);
}
</p>
(5) Load the HUAWEI CBG Root CA certificate in the static code snippet of the VerifySignatureUtil class. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">static {
// Load the preset HUAWEI CBG Root CA certificate.
File filepath = "~/certs/Huawei_cbg_root.cer";
try (FileInputStream in = new FileInputStream(filepath)) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
huaweiCbgRootCaCert = (X509Certificate) cf.generateCertificate(in);
} catch (IOException | CertificateException e) {
RUN_LOG.error("HUAWEI CBG root cert load failed!");
}
}
</p>
We have now verified the check result on the app server, and the verification result will be returned to the app for subsequent service processing.
2.4 Obtaining the System Integrity Check Result
(1) Once you complete the steps above, the app will obtain the reliable system integrity check result from the payload of the JWS string. Parse the system integrity check result from the callback API of the VerifyResultHandler class as follows:
Java:
<p style="line-height: 1.5em;">private static final class VerifyResultHandler implements ICallBack<Boolean> {
private final String jwsStr;
private final ICallBack<? super Boolean> callBack;
private VerifyResultHandler(String jwsStr, ICallBack<? super Boolean> callBack) {
this.jwsStr = jwsStr;
this.callBack = callBack;
}
@Override
public void onSuccess(Boolean verified) {
if (verified) {
// Extract the system integrity check result that has been successfully verified by the app server.
String payloadDetail = new String(Base64.decode(jwsStr.split("\\.")[1].getBytes(StandardCharsets.UTF_8), Base64.URL_SAFE), StandardCharsets.UTF_8);
try {
final boolean basicIntegrity = new JSONObject(payloadDetail).getBoolean("basicIntegrity");
// Call back the system integrity check result.
callBack.onSuccess(basicIntegrity);
} catch (JSONException e) {
…
}
}
…
}
}
</p>
(2) The following is an example of the system integrity check response:
XML:
<p style="line-height: 1.5em;">{
"apkCertificateDigestSha256": [
"osaUtTsdAvezjQBaW3IhN3/fsc6NQ5KwKuAQXcfrxb4="
],
"apkDigestSha256": "vFcmE0uw5s+4tFjXF9rVycxk2xR1rXiZFHuuBFzTVy8=",
"apkPackageName": "com.example.mockthirdapp",
"basicIntegrity": false,
"detail": [
"root",
"unlocked"
],
"nonce": "UjJScmEyNGZWbTV4YTJNZw==",
"timestampMs": 1604048377137,
"advice": "RESTORE_TO_FACTORY_ROM"
}
</p>
(3) If the value of the basicIntegrity field in the check result is false, it means that the system integrity is corrupted. In this case, the app can notify the user of any potential risks.
Conclusion
You can complete the integration by referring to the Preparations on HUAWEI Developers website. Also, you can download the SysIntegrity sample code for both Java and Kotlin from the site. And the sample code for four other functions in addition to SysIntegrity is also provided on the site.
Here is the sample code I wrote for my app. Feel free to take a look for yourself!
My sample code
What are all the features we can achieve using this kit
How this TEE works ?
Here we go
Like
Serious work.
What is the criteria for checking the Malicious apps?
Yes
Very nice and secure.
Thanks
Does Safety detect's System integrity work on Rooted device?
Huawei made their own SafetyNet :O
But why would anyone want to do this? It's annoying to legitimate users who root their device, with a lot of the people in this forum being here.
(Well, there's MagiskHide but some apps even check your list of packages and crash without even telling the user that their device is rooted)
ask011 said:
Overview
In the previous post, we learned how to integrate the UserDetect API in Safety Detect into your app to identify fake users. I've been glad to receive so much positive feedback. In this post, I'll introduce SysIntegrity (system integrity check), yet another handy function in Safety Detect. Apps can face malicious attacks when they run on insecure devices, for example, rooted devices. For certain apps, such as e-commerce apps, ensuring a secure running environment during user transactions is particularly crucial. SysIntegrity enables apps to do so by helping detect device system-related risks in advance.
I encountered this function on the HUAWEI Developers website. SysIntegrity works by integrating the Safety Detect SDK into your app, and calling the SysIntegrity API in Safety Detect. It performs the check within a Trusted Execution Environment (TEE) and signs the check result with an X.509 digital certificate to ensure that it is trustworthy and tamperproof.
Now let's take a look at what it's like in practice.
Next, I'll show you how to integrate SysIntegrity.
Content
1 Preparations
1.1 Installing Android studio
1.2 Configuring App Information in AppGallery Connect
1.3 Configuring the Huawei Maven Repository Address
1.4 Adding Build Dependencies
1.5 Configuring Obfuscation Scripts
2 Code Development
2.1 Creating a SafetyDetectClient Instance and Generating a Nonce
2.2 Calling the SysIntegrity API
2.3 Verifying the Check Result on the App Server
2.4 Obtaining the System Integrity Check Result
1. Preparations
1.1 Installing Android Studio
To install Android Studio, please refer to the following:
l Android Studio Official Website
l Android Studio Installation and Configuration
1.2 Configuring App Information in AppGallery Connect
Before developing an app, you'll need to configure the app information in AppGallery Connect. For more details, please refer to Preparations.
1.3 Configuring the Huawei Maven Repository Address
Open the build.gradle file in the root directory of your Android Studio project.
Add the AppGallery Connect plug-in and the Maven repository address.
(1) Go to buildscript > repositories and configure the Maven repository address for the HMS Core SDK.
(2) Go to allprojects > repositories and configure the Maven repository address for the HMS Core SDK.
(3) If the agconnect-services.json file has been added to the app, go to buildscript > dependencies and add the AppGallery Connect plug-in configuration.
XML:
<p style="line-height: 1.5em;">apply plugin: 'com.huawei.agconnect'
</p>
Add the build dependency in the dependencies section.
XML:
<p style="line-height: 1.5em;">dependencies {
implementation 'com.huawei.hms:safetydetect:5.0.5.302'
}
</p>
1.5 Configuring Obfuscation Scripts
If you are using AndResGuard, add its trustlist to the build.gradle file in the app directory of your project. For more details about the code, please refer to Configuring Obfuscation Scripts on the HUAWEI Developers website.
2. Code Development
2.1 Creating a SafetyDetectClient Instance and Generating a Nonce
The nonce value will be contained in the check result. You can check the nonce value to verify that the returned result corresponds to your request, and does not encounter replay attacks. A nonce value should:
l Be used only once.
l Contain 16 to 66 bytes.
l Be derived from data sent to your server (Recommended).
2.2 Calling the SysIntegrity API
(1) The SysIntegrity API has two input parameters: the nonce value (obtained during the previous step) and your app ID. You can obtain the app ID from the agconnect-services.jsonfile under the app directory of your project.
Ø Sign in to AppGallery Connect and click My projects.
Ø Find your app project and click the desired app name.
Ø Go to Project Setting > General information, and view the app ID in the App information area.
Java:
<p style="line-height: 1.5em;">private void onAdapterItemClick(int position) {
// Call the SysIntegrity API to check for risks in the payment environment.
SafetyDetectUtil.detectSysIntegrity(this, new ICallBack<Boolean>() {
@Override
public void onSuccess(Boolean baseIntegrity) {
if (baseIntegrity) {
// The system integrity is not corrupted, and the user can proceed with the purchase.
buy(productInfo);
} else {
// The system integrity is corrupted. A popup is displayed to warn the user and ask the user whether to continue.
showRootTipDialog(productInfo);
}
}
…
});
}
</p>
(3) In my app, I encapsulated the SysIntegrity API in the detectSysIntegrity method of the SafetyDetectUtil.java class. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">public static void detectSysIntegrity(final Activity activity, final ICallBack<? super Boolean> callBack) {
// Generate a nonce value.
byte[] nonce = ("Sample" + System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8);
// Read the app_id field from the agconnect-services.json file in the app directory.
String appId = AGConnectServicesConfig.fromContext(activity).getString("client/app_id");
// Obtain the Safety Detect client, call the SysIntegrity API, and add a success event listener.
SysIntegrityRequest sysintegrityrequest = new SysIntegrityRequest();
sysintegrityrequest.setAppid(appId);
sysintegrityrequest.setNonce(nonce);
// PS256 or RS256
sysintegrityrequest.setAlg("RS256");
Task task = mClient.sysIntegrity(sysintegrityrequest);
task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() {
@Override
public void onSuccess(SysIntegrityResp response) {
// Call the getResult method of the SysIntegrityResp class to obtain the check result.
String jwsStr = response.getResult();
VerifyResultHandler verifyResultHandler = new VerifyResultHandler(jwsStr, callBack);
// Send the check result to your server for verification.
verifyJws(activity, jwsStr, verifyResultHandler);
}
});
}
</p>
(4) Here, I called the relevant app server API in the verifyJws method to verify the check result. The third parameter in this method is an object of the VerifyResultHandler class, which implements a callback API to process the verification result.
2.3 Verifying the Check Result on the App Server
After receiving the check result from the TSMS server, the app will send the result to the app server. The server uses the HUAWEI CBG Root CA certificate to verify the signature and certificate chain in the check result, and thereby determines whether the check result is valid.
The sample code for the app server to read the certificate and verify the JWS string is as follows:
(1) Parse the header, payload, and signature from the JWS string.
Java:
<p style="line-height: 1.5em;">public JwsVerifyResp verifyJws(JwsVerifyReq jwsVerifyReq) {
// Obtain the JWS information sent from the app to the server.
String jwsStr = jwsVerifyReq.getJws();
// Parse the JWS segments. A JWS has three fixed segments, which are separated by periods (.).
String[] jwsSplit = jwsStr.split("\\.");
try {
// Perform Base64 decoding on each segment and construct a JWS object for each decoded segment.
JWSObject jwsObject = new JWSObject(new Base64URL(jwsSplit[0]), new Base64URL(jwsSplit[1]), new Base64URL(jwsSplit[2]));
// Verify the JWS and set the verification result.
boolean result = VerifySignatureUtil.verifySignature(jwsObject);
// Construct the response body for check result verification on the app server.
JwsVerifyResp jwsVerifyResp = new JwsVerifyResp();
jwsVerifyResp.setResult(result);
} catch (ParseException | NoSuchAlgorithmException e) {
RUN_LOG.catching(e);
}
return jwsVerifyResp;
}
</p>
(2) Use the verifySignature method of the VerifySignatureUtil class to verify relevant information, including the JWS signature algorithm, certificate chain, host name in signing certificate, and JWS signature. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">public static boolean verifySignature(JWSObject jws) throws NoSuchAlgorithmException {
JWSAlgorithm jwsAlgorithm = jws.getHeader().getAlgorithm();
// 1. Verify the JWS signature algorithm.
if ("RS256".equals(jwsAlgorithm.getName())) {
// Verify the certificate chain and obtain an instance of the Signature class based on the signature algorithm to verify the signature.
return verify(Signature.getInstance("SHA256withRSA"), jws);
}
return false;
}
private static boolean verify(Signature signature, JWSObject jws) {
// Extract the certificate chain information from the JWS header and convert the certificate chain into a proper type for subsequent processing.
X509Certificate[] certs = extractX509CertChain(jws);
// 2. Verify the certificate chain.
try {
verifyCertChain(certs);
} catch (Exception e) {
return false;
}
// 3. Verify the domain name in the signing certificate (leaf certificate). The domain name must be sysintegrity.platform.hicloud.com.
try {
new DefaultHostnameVerifier().verify("sysintegrity.platform.hicloud.com", certs[0]);
} catch (SSLException e) {
return false;
}
// 4. Verify the JWS signature information using the public key obtained from the signing certificate.
PublicKey pubKey = certs[0].getPublicKey();
try {
// Use the public key obtained from the signing certificate to initialize the Signature instance.
signature.initVerify(pubKey);
// Extract the input signature from the JWS and pass it to the Signature instance.
signature.update(jws.getSigningInput());
// Use the Signature instance to verify the signature information.
return signature.verify(jws.getSignature().decode());
} catch (InvalidKeyException | SignatureException e) {
return false;
}
}
</p>
(3) Call the extractX509CertChain method to extract the certificate chain from the JWS header. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">private static X509Certificate[] extractX509CertChain(JWSObject jws) {
List<X509Certificate> certs = new ArrayList<>();
List<com.nimbusds.jose.util.Base64> x509CertChain = jws.getHeader().getX509CertChain();
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
certs.addAll(x509CertChain.stream().map(cert -> {
try {
return (X509Certificate) certFactory.generateCertificate( new ByteArrayInputStream(cert.decode()) );
} catch (CertificateException e) {
RUN_LOG.error("X5c extract failed!");
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toList()));
} catch (CertificateException e) {
RUN_LOG.error("X5c extract failed!");
}
return (X509Certificate[]) certs.toArray();
}
</p>
(4) Call the verifyCertChain method to verify the certificate chain. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">private static void verifyCertChain(X509Certificate[] certs) throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException {
// Verify the validity period and issuing relationship of each certificate one by one.
for (int i = 0; i < certs.length - 1; ++i) {
certs[i].checkValidity();
PublicKey pubKey = certs[i + 1].getPublicKey();
certs[i].verify(pubKey);
}
// Use the preset HUAWEI CBG Root CA certificate to verify the last certificate in the certificate chain.
PublicKey caPubKey = huaweiCbgRootCaCert.getPublicKey();
certs[certs.length - 1].verify(caPubKey);
}
</p>
(5) Load the HUAWEI CBG Root CA certificate in the static code snippet of the VerifySignatureUtil class. The sample code is as follows:
Java:
<p style="line-height: 1.5em;">static {
// Load the preset HUAWEI CBG Root CA certificate.
File filepath = "~/certs/Huawei_cbg_root.cer";
try (FileInputStream in = new FileInputStream(filepath)) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
huaweiCbgRootCaCert = (X509Certificate) cf.generateCertificate(in);
} catch (IOException | CertificateException e) {
RUN_LOG.error("HUAWEI CBG root cert load failed!");
}
}
</p>
We have now verified the check result on the app server, and the verification result will be returned to the app for subsequent service processing.
2.4 Obtaining the System Integrity Check Result
(1) Once you complete the steps above, the app will obtain the reliable system integrity check result from the payload of the JWS string. Parse the system integrity check result from the callback API of the VerifyResultHandler class as follows:
Java:
<p style="line-height: 1.5em;">private static final class VerifyResultHandler implements ICallBack<Boolean> {
private final String jwsStr;
private final ICallBack<? super Boolean> callBack;
private VerifyResultHandler(String jwsStr, ICallBack<? super Boolean> callBack) {
this.jwsStr = jwsStr;
this.callBack = callBack;
}
@Override
public void onSuccess(Boolean verified) {
if (verified) {
// Extract the system integrity check result that has been successfully verified by the app server.
String payloadDetail = new String(Base64.decode(jwsStr.split("\\.")[1].getBytes(StandardCharsets.UTF_8), Base64.URL_SAFE), StandardCharsets.UTF_8);
try {
final boolean basicIntegrity = new JSONObject(payloadDetail).getBoolean("basicIntegrity");
// Call back the system integrity check result.
callBack.onSuccess(basicIntegrity);
} catch (JSONException e) {
…
}
}
…
}
}
</p>
(2) The following is an example of the system integrity check response:
XML:
<p style="line-height: 1.5em;">{
"apkCertificateDigestSha256": [
"osaUtTsdAvezjQBaW3IhN3/fsc6NQ5KwKuAQXcfrxb4="
],
"apkDigestSha256": "vFcmE0uw5s+4tFjXF9rVycxk2xR1rXiZFHuuBFzTVy8=",
"apkPackageName": "com.example.mockthirdapp",
"basicIntegrity": false,
"detail": [
"root",
"unlocked"
],
"nonce": "UjJScmEyNGZWbTV4YTJNZw==",
"timestampMs": 1604048377137,
"advice": "RESTORE_TO_FACTORY_ROM"
}
</p>
(3) If the value of the basicIntegrity field in the check result is false, it means that the system integrity is corrupted. In this case, the app can notify the user of any potential risks.
Conclusion
You can complete the integration by referring to the Preparations on HUAWEI Developers website. Also, you can download the SysIntegrity sample code for both Java and Kotlin from the site. And the sample code for four other functions in addition to SysIntegrity is also provided on the site.
Here is the sample code I wrote for my app. Feel free to take a look for yourself!
My sample code
Click to expand...
Click to collapse
Hello,
I use AppWidgetProvider on Android, this bindService Foreground widget and then when it calls Messenger I get this error (works fine if it is Activity), mMessengerService is null in sendMess method:
Java:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has
// been established, giving us the service object we can use
// to interact with the service. Because we have bound to a
// explicit service that we know is running in our own
// process, we can cast its IBinder to a concrete class and
// directly access it.
//mBoundService = ((MCBluetooth.LocalBinder)service).getService();
mMessengerService = new Messenger(service);
//mMessengerService=((MCBluetooth.LocalBinder)service).getMessenger();
Log.v(TAG,"onServiceConnected");
// Tell the user about this for our demo.
Toast.makeText(mContextWidget,
TAG+" service MCBluetoothForeground connected",
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has
// been unexpectedly disconnected -- that is, its process
// crashed. Because it is running in our same process, we
// should never see this happen.
// mBoundService = null;
mMessengerService=null;
Toast.makeText(mContextWidget.getApplicationContext(),TAG+" service MCBluetoothForeground disconnected",Toast.LENGTH_SHORT).show();
}
};
void doBindServiceForeGround() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation
// that we know will be running in our own process (and thus
// won't be supporting component replacement by other
// applications).
Intent intent=new Intent(mContextWidget, MCBluetoothForeGround.class);
mContextWidget.getApplicationContext().bindService(intent,
mConnection,Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
mContextWidget.getApplicationContext().unbindService(mConnection);
mIsBound = false;
}
}
private void sendMess(){
try {
Message message=new Message();
message.what=10;
if(mMessengerService==null){
Log.v(TAG,"mMessengerService is null");
}
mMessengerService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
Code:
2021-05-18 21:21:24.043 11598-11598/fr.jm.managercamera E/AndroidRuntime: FATAL EXCEPTION: main
Process: fr.jm.managercamera, PID: 11598
java.lang.RuntimeException: Unable to start receiver fr.jm.managercamera.MainActivityWidget: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Messenger.send(android.os.Message)' on a null object reference
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3264)
at android.app.ActivityThread.-wrap17(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1682)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:251)
at android.app.ActivityThread.main(ActivityThread.java:6572)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Messenger.send(android.os.Message)' on a null object reference
at fr.jm.managercamera.MainActivityWidget.sendCommand(MainActivityWidget.java:534)
at fr.jm.managercamera.MainActivityWidget.processVideo(MainActivityWidget.java:487)
at fr.jm.managercamera.MainActivityWidget.onReceive(MainActivityWidget.java:286)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3257)
at android.app.ActivityThread.-wrap17(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1682)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:251)
at android.app.ActivityThread.main(ActivityThread.java:6572)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Why?
Thank you.