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)
}
}