Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit e1cdd90

Browse files
Add double hash checking support for code signing (#1005)
Add double hash checking support for code signing for both android and ios SDK
1 parent 32f82e6 commit e1cdd90

File tree

5 files changed

+42
-19
lines changed

5 files changed

+42
-19
lines changed

android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ public void downloadPackage(JSONObject updatePackage, String expectedBundleFileN
257257

258258
if (isSignatureVerificationEnabled) {
259259
if (isSignatureAppearedInBundle) {
260-
CodePushUpdateUtils.verifySignature(newUpdateFolderPath, stringPublicKey);
260+
CodePushUpdateUtils.verifyFolderHash(newUpdateFolderPath, newUpdateHash);
261+
CodePushUpdateUtils.verifyUpdateSignature(newUpdateFolderPath, newUpdateHash, stringPublicKey);
261262
} else {
262263
throw new CodePushInvalidUpdateException(
263264
"Error! Public key was provided but there is no JWT signature within app bundle to verify. " +

android/app/src/main/java/com/microsoft/codepush/react/CodePushUpdateUtils.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ public static void verifyFolderHash(String folderPath, String expectedHash) {
176176
if (!expectedHash.equals(updateContentsManifestHash)) {
177177
throw new CodePushInvalidUpdateException("The update contents failed the data integrity check.");
178178
}
179+
180+
CodePushUtils.log("The update contents succeeded the data integrity check.");
179181
}
180182

181183
public static Map<String, Object> verifyAndDecodeJWT(String jwt, PublicKey publicKey) {
@@ -184,7 +186,7 @@ public static Map<String, Object> verifyAndDecodeJWT(String jwt, PublicKey publi
184186
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey)publicKey);
185187
if (signedJWT.verify(verifier)) {
186188
Map<String, Object> claims = signedJWT.getJWTClaimsSet().getClaims();
187-
CodePushUtils.log("JWT verification succeeded:\n" + claims.toString());
189+
CodePushUtils.log("JWT verification succeeded, payload content: " + claims.toString());
188190
return claims;
189191
}
190192
return null;
@@ -233,7 +235,7 @@ public static String getSignature(String folderPath) {
233235
}
234236
}
235237

236-
public static void verifySignature(String folderPath, String stringPublicKey) throws CodePushInvalidUpdateException {
238+
public static void verifyUpdateSignature(String folderPath, String packageHash, String stringPublicKey) throws CodePushInvalidUpdateException {
237239
CodePushUtils.log("Verifying signature for folder path: " + folderPath);
238240

239241
final PublicKey publicKey = parsePublicKey(stringPublicKey);
@@ -256,6 +258,10 @@ public static void verifySignature(String folderPath, String stringPublicKey) th
256258
throw new CodePushInvalidUpdateException("The update could not be verified because the signature did not specify a content hash.");
257259
}
258260

259-
CodePushUpdateUtils.verifyFolderHash(folderPath, contentHash);
261+
if (!contentHash.equals(packageHash)) {
262+
throw new CodePushInvalidUpdateException("The update contents failed the code signing check.");
263+
}
264+
265+
CodePushUtils.log("The update contents succeeded the code signing check.");
260266
}
261267
}

ios/CodePush/CodePush.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,10 @@ failCallback:(void (^)(NSError *err))failCallback;
193193
withPublicKey:(NSString *)publicKey
194194
error:(NSError **)error;
195195

196-
+ (BOOL)verifySignatureFor:(NSString *)updateFolderPath
197-
withPublicKey:(NSString *)publicKey
198-
error:(NSError **)error;
196+
+ (BOOL)verifyUpdateSignatureFor:(NSString *)updateFolderPath
197+
expectedHash:(NSString *)newUpdateHash
198+
withPublicKey:(NSString *)publicKeyString
199+
error:(NSError **)error;
199200

200201
@end
201202

ios/CodePush/CodePushPackage.m

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,18 +241,32 @@ + (void)downloadPackage:(NSDictionary *)updatePackage
241241

242242
if (isSignatureVerificationEnabled) {
243243
if (isSignatureAppearedInBundle) {
244-
BOOL isSignatureValid = [CodePushUpdateUtils verifySignatureFor:newUpdateFolderPath
245-
withPublicKey:publicKey
246-
error:&error];
244+
if (![CodePushUpdateUtils verifyFolderHash:newUpdateFolderPath
245+
expectedHash:newUpdateHash
246+
error:&error]) {
247+
CPLog(@"The update contents failed the data integrity check.");
248+
if (!error) {
249+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed the data integrity check."];
250+
}
251+
252+
failCallback(error);
253+
return;
254+
} else {
255+
CPLog(@"The update contents succeeded the data integrity check.");
256+
}
257+
BOOL isSignatureValid = [CodePushUpdateUtils verifyUpdateSignatureFor:newUpdateFolderPath
258+
expectedHash:newUpdateHash
259+
withPublicKey:publicKey
260+
error:&error];
247261
if (!isSignatureValid) {
248-
CPLog(@"Code signing integrity check error.");
262+
CPLog(@"The update contents failed code signing check.");
249263
if (!error) {
250-
error = [CodePushErrorUtils errorWithMessage:@"Code signing integrity check error."];
264+
error = [CodePushErrorUtils errorWithMessage:@"The update contents failed code signing check."];
251265
}
252266
failCallback(error);
253267
return;
254268
} else {
255-
CPLog(@"The update contents succeeded the code signing integrity check.");
269+
CPLog(@"The update contents succeeded the code signing check.");
256270
}
257271
} else {
258272
error = [CodePushErrorUtils errorWithMessage:

ios/CodePush/CodePushUpdateUtils.m

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,10 @@ + (NSDictionary *) verifyAndDecodeJWT:(NSString *)jwt
335335
}
336336
}
337337

338-
+ (BOOL)verifySignatureFor:(NSString *)folderPath
339-
withPublicKey:(NSString *)publicKeyString
340-
error:(NSError **)error
338+
+ (BOOL)verifyUpdateSignatureFor:(NSString *)folderPath
339+
expectedHash:(NSString *)newUpdateHash
340+
withPublicKey:(NSString *)publicKeyString
341+
error:(NSError **)error
341342
{
342343
NSLog(@"Verifying signature for folder path: %@", folderPath);
343344

@@ -360,16 +361,16 @@ + (BOOL)verifySignatureFor:(NSString *)folderPath
360361
return false;
361362
}
362363

364+
CPLog(@"JWT signature verification succeeded, payload content: %@", envelopedPayload);
365+
363366
if(![envelopedPayload objectForKey:@"contentHash"]){
364367
CPLog(@"The update could not be verified because the signature did not specify a content hash.");
365368
return false;
366369
}
367370

368371
NSString *contentHash = envelopedPayload[@"contentHash"];
369372

370-
return [self verifyFolderHash:folderPath
371-
expectedHash:contentHash
372-
error:error];
373+
return [contentHash isEqualToString:newUpdateHash];
373374
}
374375

375376
@end

0 commit comments

Comments
 (0)