QREncoder.mm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #import "QREncoder.h"
  2. @implementation QREncoder
  3. + (NSData*)AESEncryptString:(NSString*)string withPassphrase:(NSString*)passphrase {
  4. if (passphrase.length>kCCKeySizeAES256) {
  5. throw [NSException exceptionWithName:@"invalid passphrase exception" reason:[NSString stringWithFormat:@"passphrase too long: %lu", (unsigned long)passphrase.length] userInfo:nil];
  6. }
  7. const char* cstrPassphraseOriginal = [passphrase cStringUsingEncoding:NSUTF8StringEncoding];
  8. char cstrPassphrasePadded[kCCKeySizeAES256 + 1];
  9. memset(cstrPassphrasePadded, 0, sizeof(cstrPassphrasePadded));
  10. memcpy(cstrPassphrasePadded, cstrPassphraseOriginal, [passphrase length]);
  11. const char* dataIn = [string cStringUsingEncoding:NSUTF8StringEncoding];
  12. size_t dataInLength = [string length];
  13. size_t dataOutLength = dataInLength + kCCBlockSizeAES128;
  14. void* dataOut = malloc(dataOutLength);
  15. size_t encryptedDataLength = 0;
  16. CCCryptorStatus status = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, cstrPassphrasePadded, kCCKeySizeAES256, NULL, dataIn, dataInLength, dataOut, dataOutLength, &encryptedDataLength);
  17. NSData* encryptedData = nil;
  18. if (status==kCCSuccess) {
  19. encryptedData = [NSData dataWithBytes:dataOut length:encryptedDataLength];
  20. }
  21. free(dataOut);
  22. return encryptedData;
  23. }
  24. + (NSString*)AESDecryptString:(NSData*)string withPassphrase:(NSString*)passphrase {
  25. if (passphrase.length>kCCKeySizeAES256) {
  26. throw [NSException exceptionWithName:@"invalid passphrase exception" reason:[NSString stringWithFormat:@"passphrase too long: %lu", (unsigned long)passphrase.length] userInfo:nil];
  27. }
  28. const char* cstrPassphraseOriginal = [passphrase cStringUsingEncoding:NSASCIIStringEncoding];
  29. char cstrPassphrase[kCCKeySizeAES256 + 1];
  30. memset(cstrPassphrase, 0, sizeof(cstrPassphrase));
  31. memcpy(cstrPassphrase, cstrPassphraseOriginal, [passphrase length]);
  32. const void* dataIn = [string bytes];
  33. size_t dataInLength = [string length];
  34. size_t dataOutLength = dataInLength + kCCBlockSizeAES128;
  35. void* dataOut = malloc(dataOutLength);
  36. size_t decryptedDataLength = 0;
  37. CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, cstrPassphrase, kCCKeySizeAES256, NULL, dataIn, dataInLength, dataOut, dataOutLength, &decryptedDataLength);
  38. NSString* decryptedString = nil;
  39. if (status==kCCSuccess) {
  40. NSData* data = [NSData dataWithBytes:dataOut length:decryptedDataLength];
  41. decryptedString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
  42. }
  43. free(dataOut);
  44. return decryptedString;
  45. }
  46. + (DataMatrix*)encodeCStringWithECLevel:(int)ecLevel version:(int)version cstring:(const char*)cstring {
  47. CQR_Encode* encoder = new CQR_Encode;
  48. encoder->EncodeData(ecLevel, version, true, -1, cstring);
  49. int dimension = encoder->m_nSymbleSize;
  50. DataMatrix* matrix = [[[DataMatrix alloc] initWith:dimension] autorelease];
  51. for (int y=0; y<dimension; y++) {
  52. for (int x=0; x<dimension; x++) {
  53. int v = encoder->m_byModuleData[y][x];
  54. bool bk = v==1;
  55. [matrix set:bk x:y y:x];
  56. }
  57. }
  58. delete encoder;
  59. return matrix;
  60. }
  61. + (DataMatrix*)encodeWithECLevel:(int)ecLevel version:(int)version string:(NSString *)string AESPassphrase:(NSString*)AESPassphrase {
  62. NSData* encryptedString = [QREncoder AESEncryptString:string withPassphrase:AESPassphrase];
  63. const unsigned int len = (unsigned int)[encryptedString length];
  64. char cstring[len + 1];
  65. bzero(cstring, len + 1);
  66. [encryptedString getBytes:cstring length:len];
  67. DataMatrix* matrix = [QREncoder encodeCStringWithECLevel:ecLevel version:version cstring:cstring];
  68. return matrix;
  69. }
  70. + (DataMatrix*)encodeWithECLevel:(int)ecLevel version:(int)version string:(NSString *)string {
  71. const char* cstring = [string cStringUsingEncoding:NSUTF8StringEncoding];
  72. DataMatrix* matrix = [QREncoder encodeCStringWithECLevel:ecLevel version:version cstring:cstring];
  73. return matrix;
  74. }
  75. + (UIImage*)renderDataMatrix:(DataMatrix*)matrix imageDimension:(int)imageDimension {
  76. return [QREncoder renderDataMatrix:matrix imageDimension:imageDimension transparent:NO];
  77. }
  78. + (UIImage*)renderDataMatrix:(DataMatrix*)matrix imageDimension:(int)imageDimension transparent:(BOOL)transparent {
  79. const int bitsPerPixel = BITS_PER_BYTE * BYTES_PER_PIXEL;
  80. const int bytesPerLine = BYTES_PER_PIXEL * imageDimension;
  81. const int rawDataSize = imageDimension * imageDimension * BYTES_PER_PIXEL;
  82. unsigned char* rawData = (unsigned char*)malloc(rawDataSize);
  83. int matrixDimension = [matrix dimension];
  84. int pixelPerDot = imageDimension / matrixDimension;
  85. int offsetTopAndLeft = (int)((imageDimension - pixelPerDot * matrixDimension) / 2);
  86. int offsetBottomAndRight = (imageDimension - pixelPerDot * matrixDimension - offsetTopAndLeft);
  87. // alpha, blue, green, red
  88. const uint32_t white = 0xFFFFFFFF, black = 0xFF000000, transp = 0x00FFFFFF;
  89. uint32_t *ptrData = (uint32_t *)rawData;
  90. // top offset
  91. for(int c=offsetTopAndLeft*imageDimension; c>0; c--)
  92. *(ptrData++) = transp;
  93. for(int my=0; my<matrixDimension; my++) {
  94. uint32_t *ptrDataSouce = ptrData; // start of the row we will copy
  95. // left offset
  96. for(int c=offsetTopAndLeft; c>0; c--)
  97. *(ptrData++) = transp;
  98. for(int mx=0; mx<matrixDimension; mx++) {
  99. uint32_t clr = [matrix valueAt:mx y:my] ? black : (transparent ? transp : white);
  100. // draw one pixel line of data
  101. for(int c=pixelPerDot; c>0; c--)
  102. *(ptrData++) = clr;
  103. }
  104. // right offset
  105. for(int c=offsetBottomAndRight; c>0; c--)
  106. *(ptrData++) = transp;
  107. // then copy that row pixelPerDot-1 times
  108. for(int c=(pixelPerDot-1)*imageDimension; c>0; c--)
  109. *(ptrData++) = *(ptrDataSouce++);
  110. }
  111. // bottom offset
  112. for(int c=offsetBottomAndRight*imageDimension; c>0; c--)
  113. *(ptrData++) = transp;
  114. CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
  115. rawData,
  116. rawDataSize,
  117. FLProviderReleaseData);
  118. CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
  119. CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
  120. CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
  121. CGImageRef imageRef = CGImageCreate(imageDimension,
  122. imageDimension,
  123. BITS_PER_BYTE,
  124. bitsPerPixel,
  125. bytesPerLine,
  126. colorSpaceRef,
  127. bitmapInfo,
  128. provider,
  129. NULL,NO,renderingIntent);
  130. UIImage *newImage = [UIImage imageWithCGImage:imageRef];
  131. CGImageRelease(imageRef);
  132. CGColorSpaceRelease(colorSpaceRef);
  133. CGDataProviderRelease(provider);
  134. return newImage;
  135. }
  136. void FLProviderReleaseData(void *info, const void *data, size_t size) {
  137. free((void *)data);
  138. }
  139. @end