将Java解密转换为Swift

如何解决将Java解密转换为Swift

我正在尝试将Java代码块转换为Swift,但是我没有得到

这是我要转换的块:

https://github.com/K4CZP3R/tapo-p100-java-poc/blob/main/src/main/java/KspEncryption.java

public static C658a decodeTapoKey(String key,KspKeyPair keyPair) {
    KspDebug.out("Will try to decode the following key: " + key);
    
    try {
        byte[] decode = KspB64.decode(key.getBytes("UTF-8"));
        byte[] decode2 = KspB64.decode(keyPair.getPrivateKey());
        Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey p = kf.generatePrivate(new PKCS8EncodedKeySpec(decode2));
        instance.init(Cipher.DECRYPT_MODE,p);
        byte[] doFinal = instance.doFinal(decode);
        byte[] bArr = new byte[16];
        byte[] bArr2 = new byte[16];
        System.arraycopy(doFinal,bArr,16);
        System.arraycopy(doFinal,16,bArr2,16);
        return new C658a(bArr,bArr2);

    }
    catch (Exception ex)
    {
        KspDebug.out("Something went wrong: " + ex.getMessage());
        return null;
    }

}

这里是相同的代码,但是这次是在Python中: https://github.com/K4CZP3R/tapo-p100-python/blob/21e4bf9b61c08a3eb215293198968f82cd80ab2d/encryption.py

def decode_handshake_key(key: str,key_pair: KeyPair) -> TpLinkCipher:
    logger.debug(f"Will decode handshake key (...{key[5:]}) using current key pair")
    decode: bytes = base64.b64decode(key.encode("UTF-8"))
    decode2: bytes = base64.b64decode(key_pair.get_private_key())

    cipher = PKCS1_v1_5.new(RSA.import_key(decode2))
    do_final = cipher.decrypt(decode,None)
    if do_final is None:
        raise ValueError("Decryption failed!")

    b_arr:bytearray = bytearray()
    b_arr2:bytearray = bytearray()

    for i in range(0,16):
        b_arr.insert(i,do_final[i])
    for i in range(0,16):
        b_arr2.insert(i,do_final[i + 16])

这是我现在在Swift中不正确的内容

func decodeTapoKey(key: String,keyPair: KspKeyPair) {
        
        
        let data = key.data(using: .utf8)!
        let b64 = data.base64EncodedString(options: .lineLength76Characters)
        
        let data2 = keyPair.privateKey.data(using: .utf8)!
        let b642 = data2.base64EncodedString(options: .lineLength76Characters)
        
        do {
            
            let privateKey = try PrivateKey(pemNamed: keyPair.getPrivateKey())
            let encrypted = try EncryptedMessage(base64Encoded: key)
            let clear = try encrypted.decrypted(with: privateKey,padding: .PKCS1)

            // Then you can use:
            let data = clear.data
            let base64String = clear.base64String
            let string = try clear.string(encoding: .utf8)
           

        } catch {
            print("error")
        }

我正在尝试使用Pod SwiftyRSA。

有人可以帮我吗?

解决方法

似乎有以下情况:

  • 一个32字节的对称密钥,在服务器端以base64格式生成
  • 此32字节的密钥在服务器端已使用客户端的公共密钥加密
  • 要在客户端解密,需要使用客户端的私钥,该私钥似乎是用PKCS8格式进行base64编码的

在客户端,我们可以:

  • 用密钥构造一个EncryptedMessage
  • 创建一个PrivateKey实例
  • 随后使用私钥解密邮件
  • 然后将结果分为两个数据实例,每个数据实例各16个字节,如问题示例所示

此函数的源代码如下所示:

static func decodeTapoKey(key: String,keyPair: KspKeyPair) throws -> (Data,Data)  {
    let keyWithoutWhiteSpaces = String(key.compactMap { $0.isWhitespace ? nil : $0 })
    let encrypted = try EncryptedMessage(base64Encoded: keyWithoutWhiteSpaces)
    
    let privateKey = try PrivateKey(base64Encoded: keyPair.privateKey)
    let decryptedKey = try encrypted.decrypted(with: privateKey,padding: SecPadding.PKCS1)
    let b_arr = decryptedKey.data[0..<16]
    let b_arr2 = decryptedKey.data[16..<32]
    return (b_arr,b_arr2)
}

测试

一个人可以生成一个私有和公共测试密钥以及一个256位(= 32字节)的AES密钥。有了这些数据,我们应该获得与Python脚本相同的密钥二进制输出。

对于十六进制数据的输出,我们可以使用以下正确答案中的函数hexDescriptionhttps://stackoverflow.com/a/39075044

一个完全独立的示例:

Decrypt.swift

import Foundation
import SwiftyRSA

struct KspKeyPair {
    let privateKey: String
    let publicKey: String
}

final class Decrypt {
    
    static func decodeTapoKey(key: String,Data)  {
        let keyWithoutWhiteSpaces = String(key.compactMap { $0.isWhitespace ? nil : $0 })
        let encrypted = try EncryptedMessage(base64Encoded: keyWithoutWhiteSpaces)
        
        let privateKey = try PrivateKey(base64Encoded: keyPair.privateKey)
        let decryptedKey = try encrypted.decrypted(with: privateKey,padding: SecPadding.PKCS1)
        let b_arr = decryptedKey.data[0..<16]
        let b_arr2 = decryptedKey.data[16..<32]
        return (b_arr,b_arr2)
    }
    
}


extension Data {
    
    var hexDescription: String {
        return reduce("") {$0 + String(format: "%02x",$1)}
    }
    
}

ViewController.swift

import UIKit


class ViewController: UIViewController {
    
    let privateKey =
        """
        MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMY+gDb9hwm9gmYB+iDYxKPngQ3X
        Rm3U4tzea9NLtmHgWipM44tE4zWkEeaBawWbFjrnT0lPriTXPn6OvvDRCY7eRejB9wP/aezoNMMr
        A2XQ6Du8gcopM1ylUJCWjr9nftTb6wn75wY5IMPUKM2N0uZ+dvfQH4qEQwE05z6Iz1szAgMBAAEC
        gYAW5UcHktZSwKlbwKSzwHVNfMJB5/gBXVHqMmH/oEHrIe8n7YNmJUmce1t55L6IgjXaDbbxf5tc
        M+PK2A+jXnEc8+2snDbI1PpBepEwg5vzZ8RYnhGZT6P0/PsIqInkTIZnfXDnQ6wBapO1m9xJDe/B
        fyWMVRa6JqJtgQ0XpfG76QJBAOgKPSF5wJKC69lCbvyh38fQoeJxEKrD03FGXGBDLLYOHqfijdMT
        vcnE415994MI3fTy2dWm/yB8wZ7DvYVwVX8CQQDatuZyi6LhLhU47l5vpFsOnRWGhGrZaIN0o7N/
        1v5Vwieujrwy/yW2uCvUeXVnmohJa+sFSr29HO4PEQwWtFxNAkBXSxrKUDJ5K9Wsa0izs/YrBrsQ
        JDb/9yHBmJXCBSN57f/sateuE9wvXummr78AxcIyl3YJ4YRTZXu1za+r1qHjAkEAzjkavPKQ18W9
        2PpZLOdJvFO9EiMVJH15Rad8/pNXKMFy7RJEvcj6ZHjvSt5jJxb8Xk5VQZ4hnYkDpk0qmtXhGQJB
        AIO6TEXkHU3Sn0qTZsPmpu+EfCADLNKG43kiv74+cRzS7Th2A6E1yq5Y/lmbdpYaHqm0mKgvMHb2
        ls7DtRTYoXo=
        """
    
    let publicKey =
        """
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGPoA2/YcJvYJmAfog2MSj54EN10Zt1OLc3mvT
        S7Zh4FoqTOOLROM1pBHmgWsFmxY6509JT64k1z5+jr7w0QmO3kXowfcD/2ns6DTDKwNl0Og7vIHK
        KTNcpVCQlo6/Z37U2+sJ++cGOSDD1CjNjdLmfnb30B+KhEMBNOc+iM9bMwIDAQAB
        """
    
    let secretKey =
        """
        YyqsaPrgmVKcjS6UQY5aV0KtOdovqbuwGQMkZMoHtwygZQVy3fiLp0/03B4LKkYtIm0SBPYJw/cV
        w2DyZYsPPvX71RbuU9Pp+AJkWTfReEWhSW2vonWv6HIULK94hREHt7S51oBNXo5QP4wn2F4PD3hg
        P2DYBAw7guMy9wbGB+4=
        """
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let keyPair = KspKeyPair(privateKey: privateKey,publicKey: publicKey)
        do {
            let (b_arr,b_arr2)  = try Decrypt.decodeTapoKey(key: secretKey,keyPair: keyPair)
            print(b_arr.hexDescription)
            print(b_arr2.hexDescription)
        } catch {
            print("decoding failed: \(error)")
        }
    }
    
 
}

输出为:

4907d77a736619e6338f7e88fbed565f
40decbd392295df33afa817d23ac2824

Python

基于您的Python脚本,还有一个完全独立的示例:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
import logging
from collections import namedtuple

KspKeyPair = namedtuple('KspKeyPair',['private_key','public_key'])

logger = logging.getLogger('root')


def decode_handshake_key(key: str,keyPair: KspKeyPair):
    logger.debug(f"Will decode handshake key (...{key[5:]}) using current key pair")
    decode: bytes = base64.b64decode(key.encode("UTF-8"))
    decode2: bytes = base64.b64decode(keyPair.private_key)

    cipher = PKCS1_v1_5.new(RSA.import_key(decode2))
    do_final = cipher.decrypt(decode,None)
    if do_final is None:
        raise ValueError("Decryption failed!")

    b_arr: bytearray = bytearray()
    b_arr2: bytearray = bytearray()

    for i in range(0,16):
        b_arr.insert(i,do_final[i])
    for i in range(0,16):
        b_arr2.insert(i,do_final[i + 16])

    print(b_arr.hex())
    print(b_arr2.hex())


if __name__ == "__main__":
    privateKey = """
        MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMY+gDb9hwm9gmYB+iDYxKPngQ3X
        Rm3U4tzea9NLtmHgWipM44tE4zWkEeaBawWbFjrnT0lPriTXPn6OvvDRCY7eRejB9wP/aezoNMMr
        A2XQ6Du8gcopM1ylUJCWjr9nftTb6wn75wY5IMPUKM2N0uZ+dvfQH4qEQwE05z6Iz1szAgMBAAEC
        gYAW5UcHktZSwKlbwKSzwHVNfMJB5/gBXVHqMmH/oEHrIe8n7YNmJUmce1t55L6IgjXaDbbxf5tc
        M+PK2A+jXnEc8+2snDbI1PpBepEwg5vzZ8RYnhGZT6P0/PsIqInkTIZnfXDnQ6wBapO1m9xJDe/B
        fyWMVRa6JqJtgQ0XpfG76QJBAOgKPSF5wJKC69lCbvyh38fQoeJxEKrD03FGXGBDLLYOHqfijdMT
        vcnE415994MI3fTy2dWm/yB8wZ7DvYVwVX8CQQDatuZyi6LhLhU47l5vpFsOnRWGhGrZaIN0o7N/
        1v5Vwieujrwy/yW2uCvUeXVnmohJa+sFSr29HO4PEQwWtFxNAkBXSxrKUDJ5K9Wsa0izs/YrBrsQ
        JDb/9yHBmJXCBSN57f/sateuE9wvXummr78AxcIyl3YJ4YRTZXu1za+r1qHjAkEAzjkavPKQ18W9
        2PpZLOdJvFO9EiMVJH15Rad8/pNXKMFy7RJEvcj6ZHjvSt5jJxb8Xk5VQZ4hnYkDpk0qmtXhGQJB
        AIO6TEXkHU3Sn0qTZsPmpu+EfCADLNKG43kiv74+cRzS7Th2A6E1yq5Y/lmbdpYaHqm0mKgvMHb2
        ls7DtRTYoXo=
        """

    publicKey = """
        MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGPoA2/YcJvYJmAfog2MSj54EN10Zt1OLc3mvT
        S7Zh4FoqTOOLROM1pBHmgWsFmxY6509JT64k1z5+jr7w0QmO3kXowfcD/2ns6DTDKwNl0Og7vIHK
        KTNcpVCQlo6/Z37U2+sJ++cGOSDD1CjNjdLmfnb30B+KhEMBNOc+iM9bMwIDAQAB
        """

    secretKey = """
        YyqsaPrgmVKcjS6UQY5aV0KtOdovqbuwGQMkZMoHtwygZQVy3fiLp0/03B4LKkYtIm0SBPYJw/cV
        w2DyZYsPPvX71RbuU9Pp+AJkWTfReEWhSW2vonWv6HIULK94hREHt7S51oBNXo5QP4wn2F4PD3hg
        P2DYBAw7guMy9wbGB+4=
        """

    keyPair = KspKeyPair(privateKey,publicKey)
    decode_handshake_key(secretKey,keyPair)

此Python程序的输出与iOS Swift程序的输出完全相同。因此,Swift部分似乎可以正常工作。

Java

对于Java例程,也应该给出相同的输出。让我们用这个独立的Java示例进行测试:

package com.software7;

import org.apache.commons.codec.binary.Hex;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class Main {

    static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMY+gDb9hwm9gmYB+iDYxKPngQ3XRm3U4tzea9NLtmHgWipM44tE4zWkEeaBawWbFjrnT0lPriTXPn6OvvDRCY7eRejB9wP/aezoNMMrA2XQ6Du8gcopM1ylUJCWjr9nftTb6wn75wY5IMPUKM2N0uZ+dvfQH4qEQwE05z6Iz1szAgMBAAECgYAW5UcHktZSwKlbwKSzwHVNfMJB5/gBXVHqMmH/oEHrIe8n7YNmJUmce1t55L6IgjXaDbbxf5tcM+PK2A+jXnEc8+2snDbI1PpBepEwg5vzZ8RYnhGZT6P0/PsIqInkTIZnfXDnQ6wBapO1m9xJDe/BfyWMVRa6JqJtgQ0XpfG76QJBAOgKPSF5wJKC69lCbvyh38fQoeJxEKrD03FGXGBDLLYOHqfijdMTvcnE415994MI3fTy2dWm/yB8wZ7DvYVwVX8CQQDatuZyi6LhLhU47l5vpFsOnRWGhGrZaIN0o7N/1v5Vwieujrwy/yW2uCvUeXVnmohJa+sFSr29HO4PEQwWtFxNAkBXSxrKUDJ5K9Wsa0izs/YrBrsQJDb/9yHBmJXCBSN57f/sateuE9wvXummr78AxcIyl3YJ4YRTZXu1za+r1qHjAkEAzjkavPKQ18W92PpZLOdJvFO9EiMVJH15Rad8/pNXKMFy7RJEvcj6ZHjvSt5jJxb8Xk5VQZ4hnYkDpk0qmtXhGQJBAIO6TEXkHU3Sn0qTZsPmpu+EfCADLNKG43kiv74+cRzS7Th2A6E1yq5Y/lmbdpYaHqm0mKgvMHb2ls7DtRTYoXo=";
    static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGPoA2/YcJvYJmAfog2MSj54EN10Zt1OLc3mvTS7Zh4FoqTOOLROM1pBHmgWsFmxY6509JT64k1z5+jr7w0QmO3kXowfcD/2ns6DTDKwNl0Og7vIHKKTNcpVCQlo6/Z37U2+sJ++cGOSDD1CjNjdLmfnb30B+KhEMBNOc+iM9bMwIDAQAB";
    static String secretKey = "YyqsaPrgmVKcjS6UQY5aV0KtOdovqbuwGQMkZMoHtwygZQVy3fiLp0/03B4LKkYtIm0SBPYJw/cVw2DyZYsPPvX71RbuU9Pp+AJkWTfReEWhSW2vonWv6HIULK94hREHt7S51oBNXo5QP4wn2F4PD3hgP2DYBAw7guMy9wbGB+4=";

    public static void main(String[] args) {
        KspKeyPair keyPair = new KspKeyPair(privateKey,publicKey);
        C658a result = decodeTapoKey(secretKey,keyPair);
        System.out.println(Hex.encodeHexString(result.bArr));
        System.out.println(Hex.encodeHexString(result.bArr2));
    }

    public static C658a decodeTapoKey(String key,KspKeyPair keyPair) {
        try {
            byte[] decode = KspB64.decode(key.getBytes("UTF-8"));
            byte[] decode2 = KspB64.decode(keyPair.getPrivateKey());
            Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey p = kf.generatePrivate(new PKCS8EncodedKeySpec(decode2));
            instance.init(Cipher.DECRYPT_MODE,p);
            byte[] doFinal = instance.doFinal(decode);
            byte[] bArr = new byte[16];
            byte[] bArr2 = new byte[16];
            System.arraycopy(doFinal,bArr,16);
            System.arraycopy(doFinal,16,bArr2,16);
            return new C658a(bArr,bArr2);
        } catch (Exception ex) {
            System.out.println("Something went wrong: " + ex.getMessage());
            return null;
        }

    }
}

class C658a {
    byte[] bArr;
    byte[] bArr2;

    public C658a(byte[] bArr,byte[] bArr2) {
        this.bArr = bArr;
        this.bArr2 = bArr2;
    }
}

class KspKeyPair {
    String privateKey;
    String publicKey;

    public KspKeyPair(String privateKey,String publicKey) {
        this.privateKey = privateKey;
        this.publicKey = publicKey;
    }

    public byte[] getPrivateKey() { return privateKey.getBytes(); }
    public byte[] getPublicKey() { return publicKey.getBytes(); }
}

class KspB64 {
    public static byte[] decode(byte[] bytes) {
        return Base64.getMimeDecoder().decode(bytes);
    }
}

Java程序确实提供了相同的结果。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-