123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- package apksigner
- import (
- "regexp"
- "strconv"
- "strings"
- "text/scanner"
- "notabug.org/Umnik/GoAndroidSDK/v2/components/misc"
- )
- var (
- signerNum = regexp.MustCompile(`^Signer #(\d+)`)
- minSdkVersion = regexp.MustCompile(`^.+minSdkVersion=(\d+)`)
- maxSdkVersion = regexp.MustCompile(`^.+maxSdkVersion=(\d+)`)
- )
- // ParseDumpSignatureInfoFromBytes returns VerifyInfo from bytes
- func ParseDumpSignatureInfoFromBytes(rawData []byte) VerifyInfo {
- return ParseDumpSignatureInfoFromString(string(rawData))
- }
- // boolExtractor extracts bool value from "arg:value" line
- func boolExtractor(val string) bool {
- res, err := strconv.ParseBool(val)
- if err != nil {
- return false
- }
- return res
- }
- func getDN(line string) map[string]string {
- if strings.Contains(line, "\"") { // for example line contains `O="Ubiquiti Networks, Inc."`
- return getDNExtended(line)
- }
- value := strings.Split(line, ", ")
- res := make(map[string]string, len(value))
- for _, i := range value {
- parts := strings.SplitN(i, "=", 2)
- res[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
- }
- return res
- }
- func getDNExtended(line string) map[string]string {
- var scnr scanner.Scanner
- scnr.Init(strings.NewReader(line))
- result := map[string]string{}
- key := ""
- value := ""
- valueTrigger := false
- for token := scnr.Scan(); token != scanner.EOF; token = scnr.Scan() {
- switch token {
- case ',':
- valueTrigger = false
- key = ""
- value = ""
- case '=':
- valueTrigger = true
- default:
- if !valueTrigger {
- key += scnr.TokenText()
- } else {
- value += scnr.TokenText()
- if scnr.Peek() == ',' || scnr.Peek() == scanner.EOF {
- result[key] = value
- }
- }
- }
- }
- return result
- }
- func getNotProtectedFile(line string) string {
- return strings.TrimSpace(strings.SplitN(misc.TwoSpotValue(line), " ", 2)[0])
- }
- func getSingerNumber(line string) int {
- out := signerNum.FindStringSubmatch(line)
- return misc.IntExtractor(misc.RexSubStrSingleVal(out))
- }
- func getMinSdk(line string) int {
- out := minSdkVersion.FindStringSubmatch(line)
- return misc.IntExtractor(misc.RexSubStrSingleVal(out))
- }
- func getMaxSdk(line string) int {
- out := maxSdkVersion.FindStringSubmatch(line)
- return misc.IntExtractor(misc.RexSubStrSingleVal(out))
- }
- // ParseDumpSignatureInfoFromString returns VerifyInfo from string ers
- func ParseDumpSignatureInfoFromString(rawData string) VerifyInfo {
- infoRes := VerifyInfo{SignInfo: []SignatureInfo{}}
- index := -1 //uses for v3.1 only
- for _, rawLine := range strings.Split(rawData, "\n") {
- rawLine = strings.TrimSpace(rawLine)
- switch {
- case strings.Contains(rawLine, "using v1 scheme"):
- infoRes.V1 = boolExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.Contains(rawLine, "using v2 scheme"):
- infoRes.V2 = boolExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.Contains(rawLine, "using v3 scheme"):
- infoRes.V3 = boolExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.Contains(rawLine, "using v3.1 scheme"):
- infoRes.V3_1 = boolExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.Contains(rawLine, "using v4 scheme"):
- infoRes.V4 = boolExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "certificate DN"):
- // This is first line and we can use append
- infoRes.SignInfo = append(infoRes.SignInfo, SignatureInfo{CertDN: getDN(misc.TwoSpotRexValue(rawLine))})
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "certificate SHA-256 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].CertSHA256 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "certificate SHA-1 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].CertSHA1 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "certificate MD5 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].CertMD5 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "key algorithm"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].KeyAlgorithm = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "key size (bits)"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].KeySize = misc.IntExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "public key SHA-256 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].PubKeySHA256 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "public key SHA-1 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].PubKeySHA1 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer #") && strings.Contains(rawLine, "public key MD5 digest"):
- infoRes.SignInfo[getSingerNumber(rawLine)-1].PubKeyMD5 = misc.TwoSpotRexValue(rawLine)
- case strings.Contains(rawLine, "not protected by signature"):
- infoRes.NotProtected = append(infoRes.NotProtected, getNotProtectedFile(rawLine))
- // for v3.1 only
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "certificate DN"):
- index += 1
- // This is first line and we can use append
- infoRes.SignInfo = append(infoRes.SignInfo, SignatureInfo{CertDN: getDN(misc.TwoSpotRexValue(rawLine))})
- infoRes.SignInfo[index].MinSdk = getMinSdk(rawLine)
- infoRes.SignInfo[index].MaxSdk = getMaxSdk(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "certificate SHA-256 digest"):
- infoRes.SignInfo[index].CertSHA256 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "certificate SHA-1 digest"):
- infoRes.SignInfo[index].CertSHA1 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "certificate MD5 digest"):
- infoRes.SignInfo[index].CertMD5 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "key algorithm"):
- infoRes.SignInfo[index].KeyAlgorithm = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "key size (bits)"):
- infoRes.SignInfo[index].KeySize = misc.IntExtractor(misc.TwoSpotRexValue(rawLine))
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "public key SHA-256 digest"):
- infoRes.SignInfo[index].PubKeySHA256 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "public key SHA-1 digest"):
- infoRes.SignInfo[index].PubKeySHA1 = misc.TwoSpotRexValue(rawLine)
- case strings.HasPrefix(rawLine, "Signer (minSdkVersion=") && strings.Contains(rawLine, "public key MD5 digest"):
- infoRes.SignInfo[index].PubKeyMD5 = misc.TwoSpotRexValue(rawLine)
- }
- }
- return infoRes
- }
|