[Golang] 纯文本查看 复制代码
package main
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"flag"
"fmt"
"math"
"math/big"
"os"
"strconv"
"strings"
"time"
)
type Rsa struct {
N string
E string
P string
Q string
}
type Pemtype struct {
PrivateType string
PublicType string
}
var (
nString string
eString string
keyFile string
qBit int
)
func patchKeyfile(keyFile string, qBit int) {
ticker := time.Tick(time.Minute)
startTime := time.Now()
go func() {
for range ticker {
fmt.Println("已执行", time.Since(startTime))
}
}()
pemdata, err := os.ReadFile(keyFile)
if err != nil {
fmt.Println("keyfile错误")
return
}
block, _ := pem.Decode(pemdata)
if block == nil || block.Type != "PUBLIC KEY" {
// 处理解码错误或不是公钥类型错误
fmt.Println("keyfile错误")
return
}
newrsa, res := attackPEM(block.Bytes, qBit)
if res {
fmt.Println("新N为:")
fmt.Println(newrsa.N)
fmt.Println("新E为:")
fmt.Println(newrsa.E)
fmt.Println("新P为:")
fmt.Println(newrsa.P)
fmt.Println("新Q为:")
fmt.Println(newrsa.Q)
printKey(newrsa, 10, block.Type)
} else {
fmt.Println("生成失败")
}
fmt.Println("程序执行了", time.Since(startTime))
}
func attackPEM(blockbytes []byte, qBit int) (Rsa, bool) {
newS := Rsa{}
fmt.Println("正在生成素数合集")
primes := genPrimesMap(qBit)
fmt.Println("素数合集生成完毕")
for i, primesOfDigit := range primes {
fmt.Println("当前正在使用" + strconv.Itoa(i+1) + "位素数合集尝试分解")
ch := make(chan Rsa, len(blockbytes))
for i := range blockbytes {
go replaceAndCheck2(blockbytes, primesOfDigit, i, ch)
}
for range blockbytes {
newS = <-ch
if newS.N != "" {
return newS, true
}
}
}
return Rsa{}, false
}
func replaceAndCheck2(blockbytes []byte, primes []int, idx int, ch chan<- Rsa) {
newblock := make([]byte, len(blockbytes))
copy(newblock, blockbytes)
for i := 0; i < 255; i++ {
newblock[idx] = byte(i)
publicKeyInterface, err := x509.ParsePKIXPublicKey(newblock)
if err != nil {
// 处理解析错误
continue
}
publicKey, ok := publicKeyInterface.(*rsa.PublicKey)
if !ok {
// 处理不是RSA公钥类型错误
continue
}
nString = publicKey.N.Text(10)
eString = strconv.Itoa(publicKey.E)
n := publicKey.N
e := big.NewInt(int64(publicKey.E))
newRsa := Rsa{}
for _, p := range primes {
P, _ := new(big.Int).SetString(strconv.Itoa(p), 10)
q, r := new(big.Int).QuoRem(n, P, new(big.Int).SetInt64(0))
if q.ProbablyPrime(10) && r.Text(10) == "0" { //验证次数,越大结果越准确,但影响速度
phi := new(big.Int).Mul(new(big.Int).Sub(P, big.NewInt(1)), new(big.Int).Sub(q, big.NewInt(1)))
if new(big.Int).(nil, nil, e, phi).Cmp(big.NewInt(1)) == 0 {
newRsa.N = nString
newRsa.E = eString
newRsa.P = P.Text(10)
newRsa.Q = q.Text(10)
ch <- newRsa
}
}
}
}
ch <- Rsa{}
}
func patchN(nString string, eString string, qBit int) {
ticker := time.Tick(time.Minute)
startTime := time.Now()
go func() {
for range ticker {
fmt.Println("已执行", time.Since(startTime))
}
}()
base := 10
if nString == "" {
fmt.Println("n值异常")
return
}
var dorh bool
_, dorh = new(big.Int).SetString(nString, 10)
if !dorh {
_, dorh = new(big.Int).SetString(nString, 16)
if !dorh {
fmt.Println("n值异常!")
return
}
base = 16
}
var newrsa Rsa
newrsa, res := attackN(nString, eString, base, qBit)
if res {
fmt.Println("新N为:")
fmt.Println(newrsa.N)
fmt.Println("新E为:")
fmt.Println(newrsa.E)
fmt.Println("新P为:")
fmt.Println(newrsa.P)
fmt.Println("新Q为:")
fmt.Println(newrsa.Q)
printKey(newrsa, base, "")
} else {
fmt.Println("生成失败")
}
fmt.Println("程序执行了", time.Since(startTime))
}
func main() {
flag.StringVar(&nString, "n", "", "设置输入的n参数")
flag.StringVar(&eString, "e", "", "设置输入的e参数")
flag.StringVar(&keyFile, "key", "", "输入pem格式key文件路径")
flag.IntVar(&qBit, "b", 3, "生成用于分解的素数合集,默认为3位以内,过大影响生成时间与执行效率")
flag.Parse()
if keyFile != "" {
patchKeyfile(keyFile, qBit)
} else {
patchN(nString, eString, qBit)
}
}
func genPrimesMap(qBit int) [][]int {
primes := make([][]int, qBit)
for i := 1; i <= qBit; i++ {
previousPrimes := make([]int, 0)
if i > 1 {
previousPrimes = primes[i-2]
}
start := int(math.Pow10(i-1)) + 1
end := int(math.Pow10(i)) - 1
primes[i-1] = generatePrimes(start, end, previousPrimes)
}
return primes
}
func attackN(nStr string, eStr string, base int, qBit int) (Rsa, bool) {
newS := Rsa{}
fmt.Println("正在生成素数合集")
primes := genPrimesMap(qBit)
fmt.Println("素数合集生成完毕")
for i, primesOfDigit := range primes {
fmt.Println("当前正在使用" + strconv.Itoa(i+1) + "位素数合集尝试分解")
ch := make(chan Rsa, len(nStr))
for i := range nStr {
go replaceAndCheck(nStr, eStr, primesOfDigit, base, i, ch)
}
for range nStr {
newS = <-ch
if newS.N != "" {
return newS, true
}
}
}
return Rsa{}, false
}
func replaceAndCheck(nStr string, eStr string, primes []int, base, idx int, ch chan<- Rsa) {
newRsa := Rsa{}
e, _ := new(big.Int).SetString(eStr, base)
for i := 0; i < base; i++ {
newN := nStr[:idx] + strconv.FormatInt(int64(i), base) + nStr[idx+1:]
n, _ := new(big.Int).SetString(newN, base)
for _, p := range primes {
P, _ := new(big.Int).SetString(strconv.Itoa(p), base)
q, r := new(big.Int).QuoRem(n, P, new(big.Int).SetInt64(0))
if q.ProbablyPrime(10) && r.Text(10) == "0" { //验证次数,越大结果越准确,但影响速度
phi := new(big.Int).Mul(new(big.Int).Sub(P, big.NewInt(1)), new(big.Int).Sub(q, big.NewInt(1)))
if new(big.Int).**(nil, nil, e, phi).Cmp(big.NewInt(1)) == 0 {
newRsa.N = newN
newRsa.E = eStr
newRsa.P = P.Text(base)
newRsa.Q = q.Text(base)
ch <- newRsa
}
}
}
}
ch <- Rsa{}
}
func isPrime(num int) bool {
if num < 2 {
return false
}
for i := 2; i <= int(math.Sqrt(float64(num))); i++ {
if num%i == 0 {
return false
}
}
return true
}
func printKey(newrsa Rsa, base int, blocktype string) {
pemtype := new(Pemtype)
pStr := newrsa.P
p, _ := new(big.Int).SetString(pStr, base)
qStr := newrsa.Q
q, _ := new(big.Int).SetString(qStr, base)
nStr := newrsa.N
n, _ := new(big.Int).SetString(nStr, base)
eStr := newrsa.E
e, _ := new(big.Int).SetString(eStr, base)
// 计算 D
phiN := new(big.Int).Mul(new(big.Int).Sub(p, big.NewInt(1)), new(big.Int).Sub(q, big.NewInt(1)))
d := new(big.Int).ModInverse(e, phiN)
fmt.Println("新D为:\n" + d.Text(base))
// 创建RSA私钥
//privateKey := &rsa.PrivateKey{
// PublicKey: rsa.PublicKey{
// N: n,
// E: int(e.Int64()),
// },
// D: d,
// Primes: []*big.Int{p, q},
//}
//privateKey.Precompute()
//
//err := privateKey.Validate()
//if err != nil {
// fmt.Println(err)
// return
//}
publicKey := &rsa.PublicKey{
N: n,
E: int(e.Int64()),
}
if strings.Index(blocktype, "RSA") == -1 {
pemtype.PrivateType = "PRIVATE KEY"
pemtype.PublicType = "PUBLIC KEY"
} else {
pemtype.PrivateType = "RSA PRIVATE KEY"
pemtype.PublicType = "RSA PUBLIC KEY"
}
//生成PEM格式的私钥
//privateKeyPEM := &pem.Block{
// Type: pemtype.PrivateType,
// Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
//}
// 生成PEM格式的公钥
publicKeyBytes, _ := x509.MarshalPKIXPublicKey(publicKey)
publicKeyPEM := &pem.Block{
Type: pemtype.PublicType,
Bytes: publicKeyBytes,
}
fmt.Println("publicKeyPEM:")
_ = pem.Encode(os.Stdout, publicKeyPEM)
}
func generatePrimes(start, end int, previousPrimes []int) []int {
primes := make([]int, 0)
for i := start; i <= end; i++ {
isValid := true
for _, prime := range previousPrimes {
if i%prime == 0 {
isValid = false
break
}
}
if isValid && isPrime(i) {
primes = append(primes, i)
}
}
return primes
}