IMEI码规则

手机IMEI码由15-17位数字组成。

  • 第一部分 TAC,Type Allocation Code,类型分配码,由8位数字组成(早期是6位), 是区分手机品牌和型号的编码,该代码由GSMA及其授权机构分配。其中TAC码前两位又是分配机构标识 (Reporting Body Identifier),是授权IMEI码分配机构的代码,如01为美国CTIA,35为英国BABT,86为中国TAF。

  • 第二部分 FAC,Final Assembly Code,最终装配地代码,由2位数字构成, 仅在早期TAC码为6位的手机中存在,所以TAC和FAC码合计一共8位数字。FAC码用于生产商内部区分生产地代码。

  • 第三部分 SNR,Serial Number,序列号,由第9位开始的6位数字组成,区分每部手机的生产序列号。

  • 第四部分 CD,Check Digit,验证码,由前14位数字通过 Luhn算法计算得出。

  • 第五部分 SVN,Software Version Number,软件版本号, 区分同型号手机出厂时使用的不同软件版本,仅在部分品牌的部分机型中存在。

    • imei由15位数字组成,
    • 前6位(TAC)是型号核准号码,代表手机类型。
    • 接着2位(FAC)是最后装配号,代表产地。
    • 后6位(SNR)是串号,代表生产顺序号。
    • 最后1位 (SP)是检验码。

IMEI号码显示。只须在手机上输入“*#06#”便可以看到此手机的IMEI号码,因为IMEI号码存 储在手机电路板的“电可擦除存储器(EEPROM)”中,所以无须插入SIM卡也可以进行此项操作;
例如一部手机的IMEI号码为“447265805436460”,各个号 码代表的意思如下:
- 第1--6位数字:TAC(Type Approval Code,6位)“447265”-->型号批准号, 由欧洲型号批准中心分配。同型号的核准号码又不尽相同,如同Ericsson的GH388 和GF388就不 一样。虽然差别只有有盖无盖;但只要是同一型号的, 前六码一定一样,如果不一样,可能是冒牌 货
- 7--8位数字:FAC(Final Assembly Code,2位)"80"-->最后装配号码,表示生产厂家或最后装配所在地,由厂家进行编码。IMEI号码第7、8位数字代表的手机装配地含义如 下: 1、摩托罗拉-->07,08:德国;18:新加坡;40,41:苏格兰;44,英国; 48:香港,东南亚 改装 机;48:大陆改装机;67:美国; 68,美洲;80,81:中国;92,93:杭州东信 ; 2、 爱立信-->19:英国;51:瑞典;62:北京;61:香港;71:马来西亚; 3、诺基亚-->10:芬兰;20:德国;30:韩国;40:北京;60:东莞; 4、西门子-->37:上海; 51:德国;
- 9--14位数字:SNR(Serial Number,6位) “543646”-->序号码,这个独立序号唯一的识别每个TAC和FAC的每个移动设备。同一个品牌的同 一型号的SNR是不可能一样的,如果你发 现有二个手机的序号一模一样的话,那么其中一个是冒牌 货
- 第15位数字:SP(Spare,1位)"0"-->备用。

校验

  • 检验码计算:
    • (1).将偶数位数字分别乘以2,分别计算个位数和十位数之和
    • (2).将奇数位数字相加,再加上上一步算得的值
    • (3).如果得出的数个位是0则校验位为0,否则为10减去个位数

代码

1.校验

go语言版校验第15位

func calculateCheckDigit(prefix string) int {
    var total, sum1, sum2 int
    n := len(prefix)
    for i := 0; i < n; i++ {
        num, _ := strconv.Atoi(string(prefix[i]))
        // 奇数
        if i % 2 == 0 {
            sum1 += num
        } else { // 偶数
            tmp := num * 2
            if tmp < 10 {
                sum2 += tmp
            } else {
                sum2 = sum2 + tmp + 1 - 10
            }
        }
    }
    total = sum1 + sum2
    if (total % 10 == 0) {
        return  0
    } else {
        return  10 - (total % 10)
    }
}

python语言版,未处理第七八位

import random

def get_random_imei():
    # 随机一个长度为14字符类的数字
    num = str(random.randint(10000000000000, 99999999999999))
    # 计算最后一位校验值
    num_list = list(num)
    # 数字和
    math_sum = 0
    for i in range(1, len(num_list)+1):
        # 如果是偶数
        if i % 2 == 0:
            take_two_num = int(num_list[i-1]) * 2
            # 判断乘于2之后的数,是一位还是二位,二位的话就,
                将个位和十位上的数字相加,一位就保持不变
            if len(str(take_two_num)) == 2:
                for j in list(str(take_two_num)):
                    math_sum = int(j) + math_sum
            else:
                math_sum = take_two_num + math_sum
        # 如果是奇数的话,直接相加
        else:
            math_sum = int(num_list[i-1]) + math_sum

    # 根据math_sum得出校验位
    last_num = list(str(math_sum))[-1]
    if last_num == 0:
        check_num = 0
        imei = num + str(check_num)
        return imei

    else:
        check_num = 10 - int(last_num)
        imei = num + str(check_num)
        return imei

imei = get_random_imei()
print(imei)

2.完整生成imei go语言代码

import (
    "fmt"
    "crypto/rand"
    mrand "math/rand"
)

func main() {
    pre := CreateRandomNumber(6)
    suffix := CreateRandomNumber(6)
    // 把地区锁定到中国区
    codeImei := []string{"80", "81", "37", "40", "62", "61"}
    // 这一句很重要,加随机种子,不然会一直输出最后一个,
    mrand.Seed(time.Now().Unix())
    mid := codeImei[mrand.Intn(len(codeImei))]
    imeiStr := pre + mid + suffix
    // 计算第15位,并转换字符串
    digit := strconv.Itoa(calculateCheckDigit(imeiStr))
    // 拼接
    imei, _ := strconv.Atoi(imeiStr + digit)
    fmt.Println(imei)
    //fmt.Println(rand.Float64())   0.9405090880450124
}

func CreateRandomNumber(len int) string {
    var numbers = []byte{1, 2, 3, 4, 5, 7, 8, 9}
    var container string
    length := bytes.NewReader(numbers).Len()

    for i := 1; i <= len; i++ {
        random, _ := rand.Int(rand.Reader, big.NewInt(int64(length)))
        container += fmt.Sprintf("%d", numbers[random.Int64()])
    }
    return container
}
func calculateCheckDigit(prefix string) int {
    var total, sum1, sum2 int
    n := len(prefix)
    for i := 0; i < n; i++ {
        num, _ := strconv.Atoi(string(prefix[i]))
        // 奇数
        if i%2 == 0 {
            sum1 += num
        } else { // 偶数
            tmp := num * 2
            if tmp < 10 {
                sum2 += tmp
            } else {
                sum2 = sum2 + tmp + 1 - 10
            }
        }
    }
    total = sum1 + sum2
    if total%10 == 0 {
        return 0
    } else {
        return 10 - (total % 10)
    }
}
分类: go

浙公网安备33011302000604

辽ICP备20003309号