gpt4 book ai didi

java - PKCS1-padding/RSA 加密 ios objc 和 java 的区别

转载 作者:IT老高 更新时间:2023-10-28 21:09:14 29 4
gpt4 key购买 nike

我正在为 ios 和 Android 开发一个应用程序。我对加密任务相对较新,在过去的 3 天里,我一直把头撞在墙上,因为我无法运行 RSA 加密。

两个客户端都从 Java 服务器接收公钥。在 android 中我(显然,因为它与服务器端的代码几乎相同)没有问题,但 ios 部分似乎根本不兼容。我想用公钥加密一小段数据(aes key ),这就是我在 Java 中这样做的方式:

try {
String publickey = "MCwwDQYJKoZIhvcNAQEBBQADGwAwGAIRAK+dBpbOKw+1VKMWoFxjU6UCAwEAAQ==";
byte[] bArr = Crypto.base64Decode(publicKey, false);
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKey);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

Cipher cipher = Cipher.getInstance("RSA/NONE/PKCS1Padding", "BC");
cipher.init(1,publicKey);
int cipherBlockSize = cipher.getBlockSize();
ByteArrayOutputStream bArrOut = new ByteArrayOutputStream();
bArrOut.flush();
int pos = 0;
Log.i("ContentBufferLength", contentBuffer.length+"");

while (true) {
if (cipherBlockSize > contentBuffer.length - pos) {
cipherBlockSize = contentBuffer.length - pos;
}
Log.i("CipherBlockSize", cipherBlockSize+"");
byte[] tmp = cipher.doFinal(contentBuffer, pos, cipherBlockSize);
bArrOut.write(tmp);
pos += cipherBlockSize;
if (contentBuffer.length <= pos) {
break;
}
}
bArrOut.flush();
encryptedBuffer = bArrOut.toByteArray();
bArrOut.close();
} catch (Exception ex) {
throw ex;
}

// Log.i("Encrypted Buffer Length", encryptedBuffer.length+"");
return encryptedBuffer;

这是我的(不能正常工作的)ios代码,从这里借来的:

http://blog.wingsofhermes.org/?p=75和苹果加密练习。

-(NSString* )encryptWithPublicKey:(NSString*)key input:(NSString*) input {
const size_t BUFFER_SIZE = 16;
const size_t CIPHER_BUFFER_SIZE = 16;
//const uint32_t PADDING = kSecPaddingNone;
const uint32_t PADDING = kSecPaddingPKCS1;

static const UInt8 publicKeyIdentifier[] = "de.irgendwas.app";

NSData *publicTag;

publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];

NSMutableDictionary *publicKey2 = [[NSMutableDictionary alloc] init];
[publicKey2 setObject:kSecClassKey forKey:kSecClass];
[publicKey2 setObject:kSecAttrKeyTypeRSA forKey:kSecAttrKeyType];
[publicKey2 setObject:publicTag forKey:kSecAttrApplicationTag];
SecItemDelete((CFDictionaryRef)publicKey2);


NSData *strippedPublicKeyData = [NSData dataFromBase64String:key];

unsigned char * bytes = (unsigned char *)[strippedPublicKeyData bytes];
size_t bytesLen = [strippedPublicKeyData length];

size_t i = 0;
if (bytes[i++] != 0x30)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

/* Skip size bytes */
if (bytes[i] > 0x80)
i += bytes[i] - 0x80 + 1;
else
i++;

if (i >= bytesLen)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

if (bytes[i] != 0x30)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

/* Skip OID */
i += 15;

if (i >= bytesLen - 2)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

if (bytes[i++] != 0x03)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

/* Skip length and null */
if (bytes[i] > 0x80)
i += bytes[i] - 0x80 + 1;
else
i++;

if (i >= bytesLen)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

if (bytes[i++] != 0x00)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

if (i >= bytesLen)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

strippedPublicKeyData = [NSData dataWithBytes:&bytes[i] length:bytesLen - i];

DLog(@"X.509 Formatted Public Key bytes:\n%@",[strippedPublicKeyData description]);

if (strippedPublicKeyData == nil)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];



CFTypeRef persistKey = nil;
[publicKey2 setObject:strippedPublicKeyData forKey:kSecValueData];
[publicKey2 setObject: (kSecAttrKeyClassPublic) forKey:kSecAttrKeyClass];
[publicKey2 setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnPersistentRef];

OSStatus secStatus = SecItemAdd((CFDictionaryRef)publicKey2, &persistKey);

if (persistKey != nil) CFRelease(persistKey);

if ((secStatus != noErr) && (secStatus != errSecDuplicateItem))
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

SecKeyRef keyRef = nil;
[publicKey2 removeObjectForKey:kSecValueData];
[publicKey2 removeObjectForKey:kSecReturnPersistentRef];
[publicKey2 setObject:[NSNumber numberWithBool:YES] forKey:kSecReturnRef];
[publicKey2 setObject: kSecAttrKeyTypeRSA forKey:kSecAttrKeyType];

SecItemCopyMatching((CFDictionaryRef)publicKey2,(CFTypeRef *)&keyRef);
if (!keyRef)
[Exception raise:FAILURE function:__PRETTY_FUNCTION__ line:__LINE__ description:@"Could not set public key."];

uint8_t *plainBuffer;
uint8_t *cipherBuffer;
uint8_t *decryptedBuffer;


const char inputString[] = "1234";
int len = strlen(inputString);
// TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE
if (len > BUFFER_SIZE) len = BUFFER_SIZE-1;
plainBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));
cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t));
decryptedBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t));

strncpy( (char *)plainBuffer, inputString, len);

size_t plainBufferSize = strlen((char *)plainBuffer);
size_t cipherBufferSize = CIPHER_BUFFER_SIZE;

NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize(keyRef));
// Error handling
// Encrypt using the public.
OSStatus status = noErr;

status = SecKeyEncrypt(keyRef,
PADDING,
plainBuffer,
plainBufferSize,
&cipherBuffer[0],
&cipherBufferSize
);
NSLog(@"encryption result code: %ld (size: %lu)", status, cipherBufferSize);

return [[[NSString stringWithFormat:@"%s",cipherBuffer] dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
}

出于测试目的和简单性,目前我尝试仅加密长度为 4 个字节的输入。这应该足够小以容纳一个 block 。公钥导入和加密过程似乎有效,但是与 android 方法相比,我总是收到更长的输出。

到目前为止,我遇到的唯一区别是 SecKeyGetBlockSize 返回 16 而在 java cipher.blocksize 返回 5。我认为其他 11 个字节是为 pkcs1 填充保留的,但是如何在 ios/objc 中强制执行相同的行为?

最佳答案

尝试将密文拆分为多个部分,使每个部分包含 16 个字符长,并分别对其进行解码。我也遇到了同样的问题,但这是在 PHP 中使用了很长时间,上面的技巧对我有用。

这可能会帮助您摆脱问题。

关于java - PKCS1-padding/RSA 加密 ios objc 和 java 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12526452/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com