How to convert RSA key to ssh-rsa

I am trying to convert the generated RSA public key to SSH using Apple's security infrastructure.

Here is the code that I use to generate key pairs:

- (void)generatePrivateKey { NSDictionary *privateKeyAttr = @{(__bridge id)kSecAttrIsPermanent: @YES, (__bridge id)kSecAttrApplicationTag: self.privateTag}; NSDictionary *publicKeyAttr = @{(__bridge id)kSecAttrIsPermanent: @YES, (__bridge id)kSecAttrApplicationTag: self.publicTag}; NSDictionary *keyPairAttr = @{(__bridge id)kSecAttrKeySizeInBits: @1024, (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeRSA, (__bridge id)kSecPrivateKeyAttrs: privateKeyAttr, (__bridge id)kSecPublicKeyAttrs: publicKeyAttr}; SecKeyRef publicKey; SecKeyRef privateKey; SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKey, &privateKey); } - (NSString *)getPublicKey { NSString *contents = [self keyForTag:self.publicTag]; return [NSString stringWithFormat:@"-----BEGIN RSA PUBLIC KEY-----\n%@\n-----END RSA PUBLIC KEY-----", contents]; } - (NSString *)getPrivateKey { NSString *contents = [self keyForTag:self.privateTag]; return [NSString stringWithFormat:@"-----BEGIN RSA PRIVATE KEY-----\n%@\n-----END RSA PRIVATE KEY-----", contents]; } - (NSString *)keyForTag:(NSData *)tag { NSDictionary *queryKey = @{(__bridge id)kSecClass: (__bridge id)kSecClassKey, (__bridge id)kSecAttrApplicationTag: tag, (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeRSA, (__bridge id)kSecReturnData: @YES}; // Get the key bits. CFDataRef keyBits; OSStatus sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryKey, (CFTypeRef *)&keyBits); NSData *passDat = (__bridge_transfer NSData *)keyBits; if (sanityCheck != noErr) { passDat = nil; } NSString *contents = [passDat base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; return contents; } 

Then I get the private key as follows:

 -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQD0SvIfWFU1EzKD8rSUMWVcE9t52WtJCIKDyMPYiu3/VV9TBci7 7QocSl400yqjn5eX2piGRO5o/Wh/BKUdC/IzZbAb15jboKvgkE0R+EBnAs+zo2HJ Y1sZwT4Bc9d1ClvhHpYdE9EwpPc1IIfsz+Sa41Z0wDXqWk90A33BqIcs3wIDAQAB AoGBAMYvxx4G25mjaWgCjt1q9YAt2/COoqstbDTdu4UBsPNkn2ELYD6Vn440Bxlz 9zOnVaSsgvDrGz+x1gS2D/3woxtuqSHThEOQSHugbtDMEaZ7Pawrj7zVAZQ4PPhD l9HNf4huhAnvDA9YE73rfQst4+vq0KpPjFHCKcEaQxLu7Y4BAkEB/UeBEdXbJ2e8 ReGmH11/glszpiS+MosJIk/d68la1B5A5gSw6MO4GHNzPUnsNVKJXPYKYPmLDP33 zrYXXXb/MQJAesyFhqM6TtY6IHXQyu43e6iemzAPjx2s9l0SgNAjH25JLS7tHcXo 2gA5JcA+LqS93ei/4lLwOCd7uX9qko2JDwJBARhfdT9MbQqUoaIXSE2cO8aYTyb4 s30/7hdlwNc+UzLUNQZtLrf2iDNt29OyDsiMV/NFwRECUPsmFndG6DYcfQECQHe/ ISZd3eoq9ZvZx7Vb/zbTA3eJsmJ5KcVElVqPnPB1d15cOFWkPKD5PsEVao3JkGzp HtTw09euiPQm0CIBavkCQQC/GU6l+khFqewNmO5+cok6wSVpqw3paGL8bxIwgifT yPv42Biyf3gmXtdP//tpyXPlzn6HPqf6PqFGEGvSpPDk -----END RSA PRIVATE KEY----- 

Including this parameter in ssh-keygen calls the following public key:

 $ ssh-keygen -f test.p12 -y ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7VWIi0kXyx/UCGG91iGqKjohRLIj9hp44Xwd/pIApBHo38/noUeqN07S4oGgx47zZthg3zKFP90eEdKKOXZ0yuQKOy+yB5YAYg7e9FVvxfXCOVrGaZohh37HLUql/bdOzTK6/Upjl0ZZNYpxWyfIZ/8jKCAaTG6BhPQhLmWxCQw== 

My question is: how to make ssh-keygen with an Apple Security or OpenSSH card?

UPDATE:

Now I use OpenSSL directly and get a valid RSA key. However, the conversion still does not work correctly:

 - (NSString *)publicKey { RSA *rsa = self.rsaPrivateKey; // Encode the "ssh-rsa" string NSMutableData *sshrsa = [[NSMutableData alloc] init]; const char start[] = {0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a'}; [sshrsa appendBytes:start length:sizeof(start)]; // Encode the RSA encoding exponent e { const char *e = BN_bn2dec(rsa->e); NSString *length = [NSString stringWithFormat:@"%04lu", strlen(e)] ; [sshrsa appendData:[length dataUsingEncoding:NSUTF8StringEncoding]]; [sshrsa appendBytes:e length:strlen(e)]; } // Encode the RSA modul n { const char *n = BN_bn2dec(rsa->n); NSString *length = [NSString stringWithFormat:@"%04lu", strlen(n)] ; [sshrsa appendData:[length dataUsingEncoding:NSUTF8StringEncoding]]; [sshrsa appendBytes:n length:strlen(n)]; } return [sshrsa base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];; } 

New key

 ssh-rsa AAAAB3NzaC1yc2EAAAAG4AAAATYwvdcavn8AALOV1CoAAAAG4HHTGr5/AAAwyNcavn8AAPAq1xq+fwAAkPBhBwEAAAC2hnJUVxt7AO3JLixNzOwBALilG75/AABQsaUbvn8AAJC2pRu+fwAAELGlG75/AABZVMwDAQAAAECupRu+fwAAsJsHXP9/AAAIC7kDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHB3QAAAAAAA2IRA8A/wGr5/AAAAUvAavn8AAJBV4xq+fwAAAFLwGr5/AACQc4Ybvn8AAABS8Bq+fwAAAI4CHr5/AACQc4Ybvn8AAJBzhhu+fwAA4DGwG75/AACfAZIEAQAAAABS8Bq+fwAAUACBG75/AAA9j24JAQAAAFAAgRu+fwAAAFLwGr5/AADgMbAbvn8AAAAAAAAAAAAA4A== 

which is longer than it should be:

 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+gK0cEEgn/dDk+Sf/AdQtHp2rJoG7DxMuw2hL0+96rdKeixXVXWCE8GqMg7xIU8kSn0lrfcCJDhVBkArmlnlrZDfv1lTItBU7PvV4eDLT+3kApoqYMUmmo/ecDRyAaaOecoVZTl27RZghXcS7yxABlbVhYLzJEywOi46A9yBMFQ== 
+5
source share
2 answers

Meta: at least part of the answer, but I don't know that ObjC is doing CW to improve.

Note. This is almost a duplicate. Convert the pem key to ssh-rsa format , except that it is not ObjC in C and starts with a publication file, not a privatekey file, but the OpenSSL structure in memory for the RSA key is the same for a public or private key, when privatekey fields are ignored for publication. And it can be improved.

Your code (apparently) generates a decimal length value of 4 digits and a decimal representation of the value (unsigned, since the value is always positive) for each of e and n, but unbase64's your posted output doesn't show that any of They are actually included in the result, which, after the correct initial part matching your start , seems to be garbage, and I don't know why. You may need help debugging ObjC.

In any case, the correct encoding is a 4-byte binary (bigendian) length, followed by a binary bigendian representation of the value in two additions, which requires the addition of an initial zero byte for a positive number in the range 2 8k / 2 to 2 8k -1; this usually takes place for n, because the RSA key size is usually chosen to be a multiple of 8 (in fact, it can be 2 or a small multiple). e is rarely chosen this way, although it may be. See "String" and "mpint" at https://tools.ietf.org/html/rfc4251#section-5 .

You can do this, as in # 1011572, by calling BN_bn2bin to get the binary biennial value into a sufficiently large buffer, then encode a 4-byte length, a possible 1-byte character and a value, enough buffer. Or OpenSSL can actually do a lot for you; call BN_bn2mpi with a sufficiently large buffer, and it will do the length, possible sign and value.

How to allocate and manage a buffer (s?) In ObjC I leave you or someone else. Note that both length fields and parts of values ​​can and will often use a null byte as a valid byte value; it should not be construed as a terminator or otherwise special. A little googling tells me that this might be a problem for NSString , but I'm easily mistaken.

+3
source

Regardless, ssh-keygen is likely to be SSH specific, and the Apple Security infrastructure may not cover this.

It might be worth checking that do_print_public in ssh-keygen.c and write_key in key.c and just copy this.

Or consider using the libssh2 libssh2_userauth_publickey_fromfile function.

0
source

All Articles