NCPushNotificationEncryption.m 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //
  2. // NCPushNotificationEncryption.m
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 25/07/18.
  6. // Copyright © 2018 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. // This code derived from : Nextcloud Talk - NCSettingsController Created by Ivan Sein on 26.06.17. Copyright © 2017 struktur AG. All rights reserved.
  24. //
  25. #import "NCPushNotificationEncryption.h"
  26. #import "NCBridgeSwift.h"
  27. #import <OpenSSL/OpenSSL.h>
  28. #import <CommonCrypto/CommonDigest.h>
  29. #import "NCEndToEndEncryption.h"
  30. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  31. @implementation NCPushNotificationEncryption
  32. //Singleton
  33. + (instancetype)shared {
  34. static dispatch_once_t once;
  35. static NCPushNotificationEncryption *shared;
  36. dispatch_once(&once, ^{
  37. shared = [self new];
  38. });
  39. return shared;
  40. }
  41. - (BOOL)generatePushNotificationsKeyPair:(NSString *)account
  42. {
  43. EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
  44. if (!ctx) {
  45. return FALSE;
  46. }
  47. // Generate an new RSA KEY
  48. if (EVP_PKEY_keygen_init(ctx) <= 0) {
  49. EVP_PKEY_CTX_free(ctx);
  50. return FALSE;
  51. }
  52. if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0) {
  53. EVP_PKEY_CTX_free(ctx);
  54. return FALSE;
  55. }
  56. EVP_PKEY *pkey = NULL;
  57. if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
  58. EVP_PKEY_CTX_free(ctx);
  59. return FALSE;
  60. }
  61. // PublicKey
  62. BIO *publicKeyBIO = BIO_new(BIO_s_mem());
  63. PEM_write_bio_PUBKEY(publicKeyBIO, pkey);
  64. int len = BIO_pending(publicKeyBIO);
  65. char *keyBytes = malloc(len);
  66. BIO_read(publicKeyBIO, keyBytes, len);
  67. NSData *publicKey = [NSData dataWithBytes:keyBytes length:len];
  68. [[[NCKeychain alloc] init] setPushNotificationPublicKeyWithAccount:account data:publicKey];
  69. NSLog(@"Push Notifications public Key generated: \n%@", [[NSString alloc] initWithData:publicKey encoding:NSUTF8StringEncoding]);
  70. // PrivateKey
  71. BIO *privateKeyBIO = BIO_new(BIO_s_mem());
  72. PEM_write_bio_PKCS8PrivateKey(privateKeyBIO, pkey, NULL, NULL, 0, NULL, NULL);
  73. len = BIO_pending(privateKeyBIO);
  74. keyBytes = malloc(len);
  75. BIO_read(privateKeyBIO, keyBytes, len);
  76. NSData *privateKey = [NSData dataWithBytes:keyBytes length:len];
  77. [[[NCKeychain alloc] init] setPushNotificationPrivateKeyWithAccount:account data:privateKey];
  78. NSLog(@"Push Notifications private Key generated: \n%@", [[NSString alloc] initWithData:privateKey encoding:NSUTF8StringEncoding]);
  79. EVP_PKEY_free(pkey);
  80. EVP_PKEY_CTX_free(ctx);
  81. BIO_free(publicKeyBIO);
  82. BIO_free(privateKeyBIO);
  83. return YES;
  84. }
  85. - (NSString *)decryptPushNotification:(NSString *)message withDevicePrivateKey:(NSData *)privateKey
  86. {
  87. if (message == nil || privateKey == nil) { return nil; }
  88. NSString *privateKeyString = [[NSString alloc] initWithData:privateKey encoding:NSUTF8StringEncoding];
  89. NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:message options:0];
  90. char *privKey = (char *)[privateKeyString UTF8String];
  91. // Get Device Private Key from PEM
  92. BIO *bio = BIO_new(BIO_s_mem());
  93. BIO_write(bio, privKey, (int)strlen(privKey));
  94. EVP_PKEY *pkey = 0;
  95. PEM_read_bio_PrivateKey(bio, &pkey, 0, 0);
  96. RSA *rsa = EVP_PKEY_get1_RSA(pkey);
  97. // Decrypt the message
  98. unsigned char *decrypted = (unsigned char *) malloc(4096);
  99. int decrypted_length = RSA_private_decrypt((int)[decodedData length], [decodedData bytes], decrypted, rsa, RSA_PKCS1_PADDING);
  100. if(decrypted_length == -1) {
  101. char buffer[500];
  102. ERR_error_string(ERR_get_error(), buffer);
  103. NSLog(@"%@",[NSString stringWithUTF8String:buffer]);
  104. return nil;
  105. }
  106. NSString *decryptString = [[NSString alloc] initWithBytes:decrypted length:decrypted_length encoding:NSUTF8StringEncoding];
  107. if (decrypted)
  108. free(decrypted);
  109. free(bio);
  110. free(rsa);
  111. return decryptString;
  112. }
  113. - (NSString *)stringWithDeviceToken:(NSData *)deviceToken
  114. {
  115. const char *data = [deviceToken bytes];
  116. NSMutableString *token = [NSMutableString string];
  117. for (NSUInteger i = 0; i < [deviceToken length]; i++) {
  118. [token appendFormat:@"%02.2hhX", data[i]];
  119. }
  120. return [token copy];
  121. }
  122. @end