使用这个公钥是否能解密此加密信息?

2023-07-29 17:35:16 +08:00
 FaiChou

使用私钥 rsa 加密内容:

gl9E9ye5acVdn5MusJj0pay6y+i6qDna8DTSNHkkPjBsEE9DJ34cKhrCiNuRWIxY4+DQmrrQPMzibgCvP+3unWelxwmzMRzmSQQDTm9Z+oBiHGCcqWXtz47H/b1uoC4T6ZXkTrtuYAOVlRDn+2xKPcO9qpq5gS+cU6SPSRcRP/cAthqnLQ0FJJjY2vOqsoKda5IStxLjRSJPXs5zmJFVH/ii7J/u1vp8R6sUUNLhJmahFlODgOoEPDTW50k6O5LS8MYniZLvI/Czj9bt1z850rXGl3wHvfwmhIWH8umR5NqaPJ8/kDJXGk5ejHoljRN2GJ4iL48hvJawsoCNHpktrlqRtE6geQF74gB5hLzSvY2ZUcRo1fx7DxpPnRqfx7ctf6m7nC0vohax4NvdYJ7TWnK+oDGCJFFJRNg+L/DJlcckjWmL3nGoFYgHSfVwZXfTLOcKOtx8Pvd2Udjx+9t2/T4DqJNmhVzBvX/tEqBlv+deAbk8DaGx4FcBWm1b5j2qMUqA33OVIYLOzgFFzdMF8OqEvAPwqyg1pHjt9iPzWXWVjzFA2Z1yVou2TwZ6Z9QqrjaGyK6KfpT+h241FgCVrZgbg8g/JWU7wFHQjiEjJTSTZu6FeweQpRUuUy/A8LS0Wabh0eZQ0hcPcRBwf2gGOlmbfCojrfZNHbjRkh0Rz6YAq3T5q5VdfsKXBUMJcTilfUGRzIivVAFmM5Lx5WzgV7LsPSIuEq5sNFEypk5rrKplTirq3qE6maI3+KKbUccAs2ak6zGLtfFnJasXivwYPrivUnTDz9cV1dVFYKe72/aGnNby2TxWvNpbDu60T8BlX1CFwFj+JQyDqFu+EvgBTQ==

对应的公钥:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGhpgMD1okxLnUMCDNLCJwP/P0
UHVlKQWLHPiPCbhgITZHcZim4mgxSWWb0SLDNZL9ta1HlErR6k02xrFyqtYzjDu2
rGInUC0BCZOsln0a7wDwyOA43i5NO8LsNory6fEKbx7aT3Ji8TZCDAfDMbhxvxOf
dPMBDjxP5X3zr7cWgwIDAQAB
-----END PUBLIC KEY-----

如果解密出的结果像是下面这样,应该是对的:

{"2658844581501957149":{"file_name":"wwdc2023-10117_hd.mp4","file_size":"100597894","pick_code":"b12x4iiejvkkq83a","url":{"url":"http:\/\/xxx.xxx.com\/xxx\/wwdc2023-10117_hd.mp4?t=1690607362&u=101248331&s=1048576&d=658578066-b12x4iiejvkkq83a-0&c=2&f=1&k=ddb3d920081771b2f40ee75164c5bb1b&us=52428800&uc=10&v=1","client":2,"desc":null,"isp":null,"oss_id":"fhnfile\/xxx","ooid":""}}}

注意由于加密内容数据比较大,需要分段解密。

不管用什么方法,python/go/java 还是网上的在线解密工具,只要能解密出来即可。

我用 swift 写了分段解密,结果解密失败,用网上在线的解密工具也是失败,不知道网上的工具是不是由于不支持分段解密才失败的。

下面是我用 Swift 写的方法:

import Security
func convertPublicKey(pemString: String) -> SecKey? {
    // 1. Remove headers, newlines and spaces
    let keyString = pemString
        .replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
        .replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
        .replacingOccurrences(of: "\n", with: "")
        .replacingOccurrences(of: " ", with: "")

    // 2. Convert base64 string to Data
    guard let keyData = Data(base64Encoded: keyString) else {
        return nil
    }

    // 3. Create key dictionary
    let keyDict: [CFString: Any] = [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeyClass: kSecAttrKeyClassPublic,
        kSecAttrKeySizeInBits: NSNumber(value: 2048),
        kSecReturnPersistentRef: true
    ]

    // 4. Create SecKey from Data
    var error: Unmanaged<CFError>?
    guard let key = SecKeyCreateWithData(keyData as CFData, keyDict as CFDictionary, &error) else {
        // Handle the error here
        return nil
    }

    return key
}
let rsaKeyInSwift = convertPublicKey(pemString: rsaPublicKey)
func rsaDecrypt(data: Data) -> Data? {
    let blockSize = SecKeyGetBlockSize(rsaKeyInSwift!)
    var decryptedData = Data()
    for i in stride(from: 0, to: data.count, by: blockSize) {
        let endIndex = min(i + blockSize, data.count)
        let chunk = data[i..<endIndex]
        print(chunk)
        var error: Unmanaged<CFError>?
        guard let decryptedChunk = SecKeyCreateDecryptedData(
            rsaKeyInSwift!,
            .rsaEncryptionPKCS1,
            chunk as CFData,
            &error
        ) else {
            print("Decryption error:", error.debugDescription)
            return nil
        }
        decryptedData.append(decryptedChunk as Data)
    }

    return decryptedData
}

报错:

Decryption error: Optional(Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "RSAdecrypt wrong input (err -27)" UserInfo={numberOfErrorsDeep=0, NSDescription=RSAdecrypt wrong input (err -27)}))

在网上找到了一个开源的项目,它用 go 语言自己实现了 rsa 解密算法,不清楚为什么它不用标准库来解密。我用标准库实现的( Swift 版本)无法解密。所以不清楚是不是我的代码问题还是其他问题。

下面是 go 语言开源版本:

func rsaDecrypt(input []byte) []byte {
	output := make([]byte, 0)
	cipherSize, blockSize := len(input), rsaServerKey.Size()
	for offset := 0; offset < cipherSize; offset += blockSize {
		sliceSize := blockSize
		if offset+sliceSize > cipherSize {
			sliceSize = cipherSize - offset
		}

		n := big.NewInt(0).SetBytes(input[offset : offset+sliceSize])
		m := big.NewInt(0).Exp(n, big.NewInt(int64(rsaServerKey.E)), rsaServerKey.N)
		b := m.Bytes()
		index := bytes.IndexByte(b, '\x00')
		if index < 0 {
			return nil
		}
		output = append(output, b[index+1:]...)
	}
	return output
}

由于不熟悉 go 语言,大概看了下算法,也是计算 (n^e) mod N

所以请大家用这个公钥解密上面的内容,能否解密出来?

3258 次点击
所在节点    程序员
39 条回复
FaiChou
2023-07-29 18:58:28 +08:00
@0o0O0o0O0o #19 太强了。我对加解密确实一知半解。也很佩服那些大佬是怎么逆向出来这算法的。我只是对着逆向出来的算法重新用写一遍。
0o0O0o0O0o
2023-07-29 19:02:10 +08:00
GeruzoniAnsasu
2023-07-29 19:04:01 +08:00
sankooc
2023-07-29 19:09:21 +08:00
我解出来是 vnAD3tym1s0ape6h 开头的一堆乱码
zbinlin
2023-07-29 19:12:32 +08:00
@0o0O0o0O0o 不是 no padding ,PKCS#1 v1.5 padding 也是有这个字段串
sankooc
2023-07-29 19:12:49 +08:00
const crypto = require("crypto")
const fs = require('fs')
const path = require('path')

const data = 'gl9E9ye5acVdn5MusJj0pay6y+i6qDna8DTSNHkkPjBsEE9DJ34cKhrCiNuRWIxY4+DQmrrQPMzibgCvP+3unWelxwmzMRzmSQQDTm9Z+oBiHGCcqWXtz47H/b1uoC4T6ZXkTrtuYAOVlRDn+2xKPcO9qpq5gS+cU6SPSRcRP/cAthqnLQ0FJJjY2vOqsoKda5IStxLjRSJPXs5zmJFVH/ii7J/u1vp8R6sUUNLhJmahFlODgOoEPDTW50k6O5LS8MYniZLvI/Czj9bt1z850rXGl3wHvfwmhIWH8umR5NqaPJ8/kDJXGk5ejHoljRN2GJ4iL48hvJawsoCNHpktrlqRtE6geQF74gB5hLzSvY2ZUcRo1fx7DxpPnRqfx7ctf6m7nC0vohax4NvdYJ7TWnK+oDGCJFFJRNg+L/DJlcckjWmL3nGoFYgHSfVwZXfTLOcKOtx8Pvd2Udjx+9t2/T4DqJNmhVzBvX/tEqBlv+deAbk8DaGx4FcBWm1b5j2qMUqA33OVIYLOzgFFzdMF8OqEvAPwqyg1pHjt9iPzWXWVjzFA2Z1yVou2TwZ6Z9QqrjaGyK6KfpT+h241FgCVrZgbg8g/JWU7wFHQjiEjJTSTZu6FeweQpRUuUy/A8LS0Wabh0eZQ0hcPcRBwf2gGOlmbfCojrfZNHbjRkh0Rz6YAq3T5q5VdfsKXBUMJcTilfUGRzIivVAFmM5Lx5WzgV7LsPSIuEq5sNFEypk5rrKplTirq3qE6maI3+KKbUccAs2ak6zGLtfFnJasXivwYPrivUnTDz9cV1dVFYKe72/aGnNby2TxWvNpbDu60T8BlX1CFwFj+JQyDqFu+EvgBTQ=='
const publicKey = fs.readFileSync(path.resolve("./k.pub"), "utf8");
const raw = Buffer.from(data, "base64")
const len = raw.length
const mod = 128
const buffer = [];
for(let i = 0 ; i <= ~~(len/mod);i += 1){
const start = i * mod;
const end = Math.min(len, start + mod)
if(end == start) break;
const r1 = raw.subarray(start, end)
const rt = crypto.publicDecrypt({
key: publicKey,
}, r1)
buffer.push(rt)
}
const buf = Buffer.concat(buffer)
console.log(buf);
好像就是你要的结果 你可以试试
0o0O0o0O0o
2023-07-29 19:14:10 +08:00
@zbinlin #25 确实。。。
FaiChou
2023-07-29 19:17:02 +08:00
@GeruzoniAnsasu 对的, 被你搜到了,不过没啥好隐藏的。已经有开源版本。
FaiChou
2023-07-29 19:18:19 +08:00
@sankooc #26 谢谢,还是 js 熟悉一点,比较容易看懂(对我来讲)
zbinlin
2023-07-29 19:20:24 +08:00
那 vnAD3tym1s0ape6h 开头的就对了
FaiChou
2023-07-29 19:22:28 +08:00
@Daniate #17 确实 kSecAttrCanDecrypt 还是不行。只能手撸了。
ThirdFlame
2023-07-29 19:38:55 +08:00
那就是简单的读取公钥里面的 n, e(0x10001)
然后去密文的前 128 字节,
pow(密文 128 字节,c,e) 去掉前 11 字节,就得到明文了。
githmb
2023-07-29 20:16:38 +08:00
分段解密, 你不应该给一个字符串数组吗? 不然怎么知道你是怎么分的段, 还有你用的什么填充方式
tuwulin365
2023-07-29 21:08:15 +08:00
01FFFFFFFFFFFFFFFF00766E41443374796D31733061706536680A73DFEA7B46BE20F0AAD995D76ABEAD3C18F872FFFCD480CC7CBEAD6B1AAE25AFF6D085CF7EECFB6E4AF97CFBFC82819970BBF06D4AB318FCA9DFD19520EFEA635EF82DC6B6C5D8D964E5A42C12A666E9B6DF95D724E5BD3746BE27EAA0D295D77AB3EA2D
01FFFFFFFFFFFFFFFF0012F92DF5A6949BD979B4BE7F4CAD79FAB09087CB70B1FA6D4EA979EAB090D5CA2AEBFD3A48AA75ACF2D3D2CB7CEFFA3B4DAB73A8FD8687C971EDFB3B18F879F2E3878A9D6EBBF53A5AAC69F7A4858F8A23E2BE3319F52DADBD84869965BFFE6944AB71A1F0808A9F6EBFFF6C44A874A8F8C591CA7B
01FFFFFFFFFFFFFFFF00BAF06D4EAD74A8F8C391C97EBAFF694AAC7DAFF48BC3C47CF9A57718F41BAEF48787CA65BAFA694EFF20EEB299EBCC2DECAC3D4AFA7DFBF28183CC2DBBAE6B1DAA77FFF782819E7BBEFE3C44FE7DADF3D48FC970BDFE7620F12BFAEB8386CA66ECA4301AF22CFFABD2D4D414A694630CE830F1E78C
01FFFFFFFFFFFFFFFF0095973AFCEA2246BE28EBB0949BD926E8FB610DF72FEFAFD3DE927CF1FA681EBE7EBBA0D2D89817E2AB300CBE68BBF18F8FCC71BCF8694DBE7EBBA0CCDE8817ECA4301ABE68BBF1C6DAD52CE1976E4DAD74A8E88585CB7AEAAC2E0BBE7EBBA0DBD69517ECA4301ABE3FA3E78F83CA7FBCF1684CA975
01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00A1F08283C370BCFE3C80D1

解出来是这么一串东西😎
tuwulin365
2023-07-29 21:11:06 +08:00
N 是
8686980c0f5a24c4b9d43020cd2c22703ff3f450756529058b1cf88f09b8602136477198a6e2683149659bd122c33592fdb5ad47944ad1ea4d36c6b172aad6338c3bb6ac6227502d010993ac967d1aef00f0c8e038de2e4d3bc2ec368af2e9f10a6f1eda4f7262f136420c07c331b871bf139f74f3010e3c4fe57df3afb71683

密文是
825F44F727B969C55D9F932EB098F4A5ACBACBE8BAA839DAF034D23479243E306C104F43277E1C2A1AC288DB91588C58E3E0D09ABAD03CCCE26E00AF3FEDEE9D67A5C709B3311CE64904034E6F59FA80621C609CA965EDCF8EC7FDBD6EA02E13E995E44EBB6E6003959510E7FB6C4A3DC3BDAA9AB9812F9C53A48F4917113FF7
00B61AA72D0D052498D8DAF3AAB2829D6B9212B712E345224F5ECE739891551FF8A2EC9FEED6FA7C47AB1450D2E12666A116538380EA043C34D6E7493A3B92D2F0C6278992EF23F0B38FD6EDD73F39D2B5C6977C07BDFC26848587F2E991E4DA9A3C9F3F9032571A4E5E8C7A258D1376189E222F8F21BC96B0B2808D1E992DAE
5A91B44EA079017BE2007984BCD2BD8D9951C468D5FC7B0F1A4F9D1A9FC7B72D7FA9BB9C2D2FA216B1E0DBDD609ED35A72BEA0318224514944D83E2FF0C995C7248D698BDE71A815880749F5706577D32CE70A3ADC7C3EF77651D8F1FBDB76FD3E03A89366855CC1BD7FED12A065BFE75E01B93C0DA1B1E057015A6D5BE63DAA
314A80DF73952182CECE0145CDD305F0EA84BC03F0AB2835A478EDF623F35975958F3140D99D72568BB64F067A67D42AAE3686C8AE8A7E94FE876E35160095AD981B83C83F25653BC051D08E212325349366EE857B0790A5152E532FC0F0B4B459A6E1D1E650D2170F7110707F68063A599B7C2A23ADF64D1DB8D1921D11CFA6
00AB74F9AB955D7EC2970543097138A57D4191CC88AF5401663392F1E56CE057B2EC3D222E12AE6C345132A64E6BACAA654E2AEADEA13A99A237F8A29B51C700B366A4EB318BB5F16725AB178AFC183EB8AF5274C3CFD715D5D54560A7BBDBF6869CD6F2D93C56BCDA5B0EEEB44FC0655F5085C058FE250C83A85BBE12F8014D
Leon406
2023-07-29 21:18:00 +08:00
就一个简单 RSA 公钥解密,没什么难度


FaiChou
2023-07-29 21:56:38 +08:00
@tuwulin365 #34 哈哈对的,去掉 01...00 的填充就是了
fox0001
2023-07-30 02:19:43 +08:00
看完了所有回复,还是没弄懂 up 主的问题在哪里。

1. 私钥加密,公钥解密,确实不是为了加密,可能用作签名、防篡改之类的需求。或者是避免直接明文传输,实现类似 base64 的混淆效果。
2. 我们的 Java 项目也有类似的应用,但我们没有撸过相关加密解密的算法,也能成功解密。
3. 既然 up 主都能解密出来,那为什么要提问“能否解密此加密信息”?
happyxhw101
2023-07-30 19:56:55 +08:00
如果加密内容比较大,建议 rsa + aes
rsa 加密 aes 秘钥,aes 加密文件,此外 aes ctr 可以实现 stream 加密

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

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

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

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

© 2021 V2EX