哪位朋友帮忙用 mac 测试下我的 Python 脚本

7 月 10 日
 gosky

把输出贴给我
如果有异常,如果能附带帮忙 fix 更好

import signal
import subprocess
from typing import OrderedDict

APP_NAME = "Hello"


class CalledProcessError(subprocess.CalledProcessError):
    """
    `subprocess.CalledProcessError` does not print `stderr` and `output`.
    """

    def __str__(self):
        if self.returncode and self.returncode < 0:
            try:
                return "Command '%s' died with %r." % (
                    self.cmd,
                    signal.Signals(-self.returncode),
                )
            except ValueError:
                return "Command '%s' died with unknown signal %d." % (
                    self.cmd,
                    -self.returncode,
                )
        else:
            return (
                "Command '%s' returned non-zero exit status %d. stderr: '%s'. output: '%s'"
                % (self.cmd, self.returncode, self.stderr.strip(), self.output.strip())
            )


class DecryptError(Exception): ...


class DarwinCryptex:
    scheme = "security"

    def encrypt(self, attrs: OrderedDict[str, str], plaintext: str) -> str:
        account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
        cmd = [
            "security",
            "add-generic-password",
            "-a",
            account,
            "-s",
            APP_NAME,
            "-w",
            plaintext,
            "-U",
        ]
        r = subprocess.run(
            cmd,
            capture_output=True,
            encoding="utf-8",
            text=True,
            timeout=5,
        )
        if r.returncode != 0:
            raise CalledProcessError(
                r.returncode, cmd, output=r.stdout, stderr=r.stderr
            )
        return "******"

    def decrypt(self, attrs: OrderedDict[str, str], ciphertext: str) -> str:
        account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
        cmd = [
            "security",
            "find-generic-password",
            "-a",
            account,
            "-s",
            APP_NAME,
            "-w",
        ]
        r = subprocess.run(
            cmd,
            capture_output=True,
            encoding="utf-8",
            text=True,
            timeout=5,
        )
        if r.returncode == 0:
            return r.stdout.strip()
        elif r.returncode == 44:
            raise DecryptError()
        else:
            raise CalledProcessError(
                r.returncode, cmd, output=r.stdout, stderr=r.stderr
            )

    def clean(self, attrs: OrderedDict[str, str]):
        account = "-".join([f"{k}:{v}" for k, v in attrs.items()])
        cmd = ["security", "delete-generic-password", "-a", account, "-s", APP_NAME]
        r = subprocess.run(
            cmd, capture_output=True, encoding="utf-8", text=True, timeout=5
        )
        if r.returncode not in (0, 44):
            raise CalledProcessError(
                r.returncode, cmd, output=r.stdout, stderr=r.stderr
            )


cryptex = DarwinCryptex()
attrs: OrderedDict[str, str] = OrderedDict(
    [
        ("app", "test"),
        ("section", "hello"),
        ("key", "你好"),
    ]
)
plaintext = "Hello world! 你好,世界!"

try:
    ciphertext = cryptex.encrypt(attrs, plaintext)
    decrypted = cryptex.decrypt(attrs, ciphertext)
    assert decrypted == plaintext

    mismatch_attrs = attrs.copy()
    mismatch_attrs["needless"] = "有毒"
    try:
        cryptex.decrypt(mismatch_attrs, ciphertext)
    except DecryptError:
        pass
    else:
        raise AssertionError("Expected DecryptError")
finally:
    cryptex.clean(attrs)

16213 次点击
所在节点    Python
12 条回复
busln
7 月 10 日
assert decrypted == plaintext

不成立报错了

且 encrypt 是不是没写完全呀
gosky
7 月 10 日
@busln
感觉是写完了
把两个变量都打印瞧瞧?
busln
7 月 10 日
程序有问题, 没写进去
gosky
7 月 10 日
@busln 我用 claude review 了下,没大问题啊
zhhanging
7 月 10 日
assert 失败,打印两个变量如下
decrypted: 48656c6c6f20776f726c642120e4bda0e5a5bdefbc8ce4b896e7958cefbc81
plaintext: Hello world! 你好,世界!
应该是遇到非 ascii 字符给他转成 hex 了
gosky
7 月 10 日
@zhhanging
"Hello world! 你好,世界!".encode('utf-8').hex()
刚好是
'48656c6c6f20776f726c642120e4bda0e5a5bdefbc8ce4b896e7958cefbc81'
busln
7 月 10 日
finally 给删了,漏看了
@gosky
busln
7 月 10 日
bytes.fromhex(hex).decode("utf-8")
这样就能转换回来了
gosky
7 月 10 日
@busln
把下面的中文字符,全换成英文字母,会怎么样?

attrs: OrderedDict[str, str] = OrderedDict(
[
("app", "test"),
("section", "hello"),
("key", "你好"),
]
)
plaintext = "Hello world! 你好,世界!"
keakon
7 月 10 日
你在 github 上建个 ci ,让它用 macos 的容器跑不就行了。。
gosky
7 月 10 日
@keakon 是的。正这么玩着。感谢
wenrouxiaozhu
7 月 10 日
开虚拟机+黑苹果也行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1226427

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX